Git Product home page Git Product logo

candle's Introduction

logo

Candle

2D lighting for SFML

Candle is a SFML based C++ library that provides light, shadow casting and field of view functionalities with easy integration.

Official documentation.

Contents

Demo

Before anything, here you have a little example of how it looks.

The code comes with a demo program showing the functionalities provided by the library. In it you can place lights and edges that will cast shadows, and modify the behaviour of the fog.

You can check the full manual of the demo here.

Build

CMake

You can build the static library and the demo program with CMake.

mkdir build && cd build
cmake .. -DBUILD_DEMO=ON
cmake --build .

This will generate libCandle-s.a or (Candle-s.lib on Windows) in build/lib folder, and the demo program (or demo.exe) in build/bin.

Make

Alternatively, if you work in Linux, you can use make, and also build the docs with it.

make
make docs # optional	

Requisites

  • SFML v2.5.1
    • Graphics module and System module.

This library is meant to be used in SFML applications, so it's assumed that you are familiar with the process of compiling them. If you are not, you can learn in the official website .

  • If you want to build the docs, Doxygen 1.9.1 is required.

Contributors

Thanks to the people that have contributed to this project: (emoji key)


Modar Nasser

🐛 🚇 📖

nightroy99

🌍 👀

Lukas Dürrenberger

🐛

Tim Stoddard

💻 🐛 ⚠️

Dead-Deus

🚇 🐛

GuillaumeG.

🐛 ⚠️ 💻 🤔

This project follows the all-contributors specification.

Contributing

  • Read the contributing guidelines if you want to contribute to the code.
  • Open a new issue (issues) to make a request or report a bug.
  • Alternatively, comment it on the SFML forum
  • If you use it in a project, you don't have to give any credit. But if you did so, that would be fantastic!
  • And of course, ⭐ star this repository and give it some visibility (stargazers).

Example program

I will assume that you have SFML installed in your system. If we have a project with the following structure:

|- project
   |- libCandle-s.a
   |- main.cpp
   |- include
      |- Candle
         |- Candle.hpp
         |- ... # Candle headers

the main.cpp file could look like this:

#include <SFML/Graphics.hpp>
#include "Candle/RadialLight.hpp"
 
int main(){
    // create window
    sf::RenderWindow w(sf::VideoMode(400, 400), "app");
    
    // create a light source
    candle::RadialLight light;
    light.setRange(150);
    
    // create an edge pool
    candle::EdgeVector edges;
    edges.emplace_back(sf::Vector2f(200.f, 100.f), 
                       sf::Vector2f(200.f, 300.f));
    
    // main loop
    while(w.isOpen()){
        sf::Event e;
        while(w.pollEvent(e)){
            if(e.type == sf::Event::Closed){
                w.close();
            }else if(e.type == sf::Event::MouseMoved){
                sf::Vector2f mp(sf::Mouse::getPosition(w));
                light.setPosition(mp);
                light.castLight(edges.begin(), edges.end());
            }
        }
        
        w.clear();
        w.draw(light);
        w.display();
    }
    return 0;
}

We can compile it with the following command:

g++ -o app main.cpp -Iinclude -L. -lCandle-s -lsfml-graphics -lsfml-window -lsfml-system

And we run it

./app

The result will be a simple light casting a shadow over an invisible wall in the center of the window.

License

Candle uses the MIT license, a copy of which you can find here, in the repo.

It uses the external library SFML, that is licensed under the zlib/png license.

candle's People

Contributors

allcontributors[bot] avatar dead-deus avatar jonathspirit avatar madour avatar miguelmj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

candle's Issues

Can`t compile on Linux

I can`t compile on Linux, because «numeric_limits» not an element «std».
File "Candle/geometry/Line.hpp"

/**
 * @file
 * @author Miguel Mejía Jiménez
 * @copyright MIT License
 * @brief This file contains the Line struct and main raycast algorithm.
 */
#ifndef __SFML_UTIL_GEOMETRY_LINE_HPP__
#define __SFML_UTIL_GEOMETRY_LINE_HPP__

#include <limits> //<--------------------------------------------------------------------------- Must be added

#include <SFML/System/Vector2.hpp>

#include "Candle/geometry/Vector2.hpp"
#include "Candle/Constants.hpp"

M_PI is non-standard

You're using M_PI in parts of the code, unfortunately this constant isn't really defined in the standard and while available in most compilers, some compilers, like MSVC require additional steps to use it.
On top of that, since you use M_PI in a header file, the library user now also has to deal with it in their codebase.

Steps to Reproduce

Build Candle with MSVC (2019)

Actual Behavior

RadialLight.cpp(24,22): error C2065: 'M_PI': undeclared identifier
Line.cpp(14,30): error C2065: 'M_PI': undeclared identifier
Line.cpp(15,43): error C2065: 'M_PI': undeclared identifier
Line.cpp(15,56): error C2065: 'M_PI': undeclared identifier
Line.cpp(17,20): error C2065: 'M_PI': undeclared identifier

Expected Behavior

Candle builds without errors

Solutions

  • You could add add_definition(-D_USE_MATH_DEFINES) to your CMake file in a scope for MSVC
  • Add #define _USE_MATH_DEFINES in front of every <cmath> include
  • Use a custom constant for PI

Version 2.0

A new version is necessary.

This library is a it old now and there are several things that could have been done better.
The pending feature (now frozen) to allow light texturing #29
and some issues with the overal approach #37 #36
are signals notorious enough that Candle is a bit outdated.

Not to mention that SFML 2.6 is out and honestly, I'm not sure if there is something there that could benefit this project.

So I'm opening this issue to track the main features desired for Candle 2.0

  • Light texturing (implement with shaders)
  • A new approach to avoid use of pointers and ensure null safety
  • A review of the underlying geometry
  • A revamp for the occlusion system (currently called segments)

Also, after these years I've learned one or two things more about graphic engines, so other features that would be cool to have (but have no priority for Candle 2.0) are:

  • A light layer system (occluders only affect lights in the same layer)
  • Normal maps (a separate texture to define how a surface reacts to light)

I don't have much time for this project right now, given the size of the pending changes, but I'm determined to keep it a modern, usable library. So even if the updates arrive slowly, be sure I have the will to work on them.

Build when SFML as subdirectory

# might need to set manually SFML_ROOT to the install location of SFML for Windows users
# set(SFML_ROOT "")
if(SFML_ROOT STREQUAL "") --------------------------------------------------> need if statment 
	find_package(SFML 2.5 REQUIRED COMPONENTS  graphics)
endif()

if i build in windows without packet manager and sfml just subdirectory, i don`t need find sfml, just set(SFML_ROOT "")

Mutex Lock crash when initialising RadialLight when linking static library.

I've manged to build the demo from the source code without issues, however when trying to link the compiled lib into another project I get issues with the RadialLight class.

I define the RadialLight in the header of a game state class (using my own framework built on top of SFML) like so:

#pragma once

#include <VFrame/VState.h>
#include <Candle/Candle.hpp>

class PlayState : public VState
{
public:
	typedef VState VSUPERCLASS;
	PlayState() = default;

	virtual void Initialise() override;
	virtual void Update(float dt) override;
	virtual void Draw(sf::RenderTarget& RenderTarget) override;

	candle::RadialLight light;
	candle::EdgeVector edges;
};

Also, implement a test example in the cpp like so:

#include "PlayState.h"
#include <VFrame/VGlobal.h>

#include "PauseScreen.h"

#include <Candle/Candle.hpp>

void PlayState::Initialise()
{
	VSUPERCLASS::Initialise();

	light.setRange(150);
	edges.emplace_back(
		sf::Vector2f(200.f, 100.f),
		sf::Vector2f(200.f, 300.f));
}

void PlayState::Update(float dt)
{
	VSUPERCLASS::Update(dt);

	light.setPosition(VGlobal::p()->GetMousePosition());
	light.castLight(edges.begin(), edges.end());

	if (VGlobal::p()->Input->IsButtonPressed("Pause"))
	{
		OpenSubState(new PauseScreen());
	}
}

void PlayState::Draw(sf::RenderTarget& RenderTarget)
{
	VSUPERCLASS::Draw(RenderTarget);
	RenderTarget.draw(light);
}

It compiles in Visual Studio 2017, but when I try to run I get a crash from an Access Violation within MutexImpl::lock(). Going down the call stack, the source is the RadialLight class when calling the default constructor on the two sf::Texture objects within RadialLight.cpp:

namespace candle{
    const float BASE_RADIUS = 400.0f;
    bool l_texturesReady(false);
    sf::Texture l_lightTextureFade;
    sf::Texture l_lightTexturePlain;
      
    void initializeTextures(){

I've found one way to resolve the crash, however. You can change these two to pointers (or better, smart unique pointers) and initialise the pointers in the initializeTextures function, that way the textures don't try to initialise before the main function is called.

std::unique_ptr<sf::Texture> l_lightTextureFade;
std::unique_ptr<sf::Texture> l_lightTexturePlain;

If you want to avoid smart pointers for compatibility, you could use raw pointers but then you would need to add a way to delete the pointer when the user wants to close the application.

Directed light not casting shadow at 90º

With the last fixes, now directed lights don't cast shadows when they have a 90º rotation. I'm not sure whether it has to do with the line intersection calculation, but this surely didn't happen before.

Capture 1

candle-capture-211018153635

Capture 2

candle-capture-211018154104

@JonathSpirit just mentioning you in case you want to be aware.

candle::RadialLight has an offset origin point

For some reason RadialLight has an offset origin. It mean that even setting origin to (0, 0) breaks everything which makes no sense to me

    // ...
    const float BASE_RADIUS = 400.0f;
    // ...
    RadialLight::RadialLight()
        : LightSource()
        {
        if(!l_texturesReady){
            // The first time we create a RadialLight, we must create the textures
            initializeTextures();
            l_texturesReady = true;
        }
        m_polygon.setPrimitiveType(sf::TriangleFan);
        m_polygon.resize(6);
        m_polygon[0].position =
        m_polygon[0].texCoords = {BASE_RADIUS+1, BASE_RADIUS+1};
        m_polygon[1].position =
        m_polygon[5].position =
        m_polygon[1].texCoords =
        m_polygon[5].texCoords = {0.f, 0.f};
        m_polygon[2].position =
        m_polygon[2].texCoords = {BASE_RADIUS*2 + 2, 0.f};
        m_polygon[3].position =
        m_polygon[3].texCoords = {BASE_RADIUS*2 + 2, BASE_RADIUS*2 + 2};
        m_polygon[4].position =
        m_polygon[4].texCoords = {0.f, BASE_RADIUS*2 + 2};
        Transformable::setOrigin(BASE_RADIUS, BASE_RADIUS);
        setRange(1.0f);
        setBeamAngle(360.f);
        // castLight();
        s_instanceCount++;
    }

Weird snap shadow glitch

shadowSnapBug

When casting to a complex shape, weird shadow snap appear and make it uncomfortable to see.

I created lines between those points :

point 0 x: 160 y: 120
point 1 x: 200 y: 160
point 2 x: 160 y: 200
point 3 x: 120 y: 160

My code is from the example program, with the add of a lighting area :

candle::LightingArea fog(candle::LightingArea::FOG,
                             sf::Vector2f(0.f, 0.f),
                             sf::Vector2f(640.f, 480.f));
    fog.setAreaColor(sf::Color(0,0,0,100));

I used the library imgui-sfml but this should not interfere with candle.

Are there ports to other langues?

Hello,

I would like to know, if its possible, if there are ports to other language favorable for .NET or Java?

Best regards pizzadox

Shadow display error

Environment

Windows11
VS2022
SFML-2.5.1
Candle-1.0.2
set(SFML_STATIC_LIBRARIES TRUE)

Screenshot

image

setColor on RadialLight doesn't change color

So have got all my RadialLight's working like normal but when using .setColor say sf::color::red for example, there is no change in the light color at all? but examples shows it works?

This is compiled with static SFML with /MT option enabled.

Also had an exit error where candle gives an access violation when you exit program which i fixed by manually calling the destructor for RadialLight on every single one made.

Compiled using Visual C++ 2019, /MT

Make include headers - PUBLIC

Make
target_include_directories(Candle-s PRIVATE include)
to
target_include_directories(Candle-s PUBLIC include)
Because I can`t include library as add_subdirectory(), I must write bypassing
target_include_directories(${PROJECT_NAME} PRIVATE extlibs/Candle/include)

Mine CMakeLists.txt

cmake_minimum_required(VERSION 3.18.4)

project(Spark)

set(INCROOT include/Spark)
set(SRCROOT src)

set(SRC 
    ${SRCROOT}/Main.cpp
)

add_executable(${PROJECT_NAME} ${SRC})
target_include_directories(${PROJECT_NAME} PRIVATE ${INCROOT})

find_package(SFML COMPONENTS system window graphics REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE sfml-system sfml-window sfml-graphics)

add_subdirectory(extlibs/Candle)
target_link_libraries(${PROJECT_NAME} PRIVATE Candle-s)
#target_include_directories(${PROJECT_NAME} PRIVATE extlibs/Candle/include) <----- It`s too much, it`s bad

add_custom_command(                                                                                                                                                       
    TARGET ${PROJECT_NAME}
    POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
    ${CMAKE_SOURCE_DIR}/assets
    ${CMAKE_SOURCE_DIR}/build/assets
)

Candle CMakeLists.txt

cmake_minimum_required(VERSION 3.12)

project(Candle)

# set C++11 standard
set(CMAKE_CXX_STANDARD 11)

# set output files directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY lib)


# might need to set manually SFML_ROOT to the install location of SFML for Windows users
# set(SFML_ROOT "")

# if the user wants to use static SFML libs
# set(SFML_STATIC_LIBRARIES TRUE)

find_package(SFML 2.5 REQUIRED COMPONENTS  graphics)


set(CANDLE_SRC

	src/LightingArea.cpp
	src/LightSource.cpp
	src/RadialLight.cpp
	src/DirectedLight.cpp
	src/Line.cpp
	src/Polygon.cpp
	src/Color.cpp
	src/VertexArray.cpp
	src/Constants.cpp

)

# Static library target
add_library(Candle-s STATIC ${CANDLE_SRC})
target_include_directories(Candle-s PRIVATE include) <------------------------- Must be public
target_link_libraries(Candle-s sfml-graphics)

option(RADIAL_LIGHT_FIX "Use RadialLight fix for errors with textures" OFF)

if(RADIAL_LIGHT_FIX)
	target_compile_definitions(Candle-s PUBLIC -DRADIAL_LIGHT_FIX)
endif()


# Demo target
option(BUILD_DEMO "Build demo application" OFF)

if (BUILD_DEMO)
	set(DEMO_SRC demo.cpp)
	add_executable(demo ${DEMO_SRC})
	target_include_directories(demo PRIVATE include)
	target_link_libraries(demo PRIVATE sfml-graphics Candle-s)
endif()

#RadialLightFix deconstructor problem along with Access Violations

Hello, when i have this enabled with static /mt option compiled with Visual Studio 2019
.lib also compiled with /MT

Randomly sometimes the deconstructor gets called without warning and crashes while trying to draw the radialight

I completely removed the deconstructor and decided to call it manually and its fixed

100% The deconstructor was at fault and being called "Randomly",, this was happening with just a simple radiallight being initalized and drawn like so:

`// create a light source
		candle::RadialLight light;
		light.setRange(150);
		this->lightsources.push_back(light);`

candle::LightingArea fog(candle::LightingArea::FOG,
				sf::Vector2f(0.f, 0.f),
				sf::Vector2f(680, 480.f));
				fog.setAreaColor(sf::Color::Black);
				fog.setAreaOpacity(fogopacity);

				fog.clear();
				for (int i = 0; i < this->lightsources.size(); ++i)
				{
					fog.draw(lightsources[i]);//would randomly deconstruct this and then draw and then crash
				}
				for (int i = 0; i < this->lightsources2.size(); ++i)
				{
					fog.draw(lightsources2[i]);
				}
				fog.display();

				Device->draw(fog);

And here was the modifications i made to fix the error in the Memory Module / .lib
image

SFML Event Closed:
image

Which results in:
image

image

Why pointers instead of references?

One small question. What is the reason of using a pointer to a texture in, for example, LightingArea constructor? Because this way it feels really separated from the SFML design principles...

Add all .hpp files in CMakeLists.txt

it may be a matter of taste, but I think it's right

set(

        # Add all .hpp files, because in project structure they are hidden  

	src/LightingArea.cpp
	src/LightSource.cpp
	src/RadialLight.cpp
	src/DirectedLight.cpp
	src/Line.cpp
	src/Polygon.cpp
	src/Color.cpp
	src/VertexArray.cpp
	src/Constants.cpp
        

)

Use of shaders

The lights with the fade flag on currently use a custom texture (at least in RadialLight). This should be replaced by the usage of a shader, also because of the customiaztion it would allow through setUniform (for example to change fade linearity). Also, this can lead for better effects of light in the future (blur the edges of the light for softer lights).

Potentially useful resources:

Error building with `make`

OS : Linux Manjaro

Tried to compile using the Makefile :

make prep
-> debug/demo.d : File does not exist

then I try make, the file debug/demo.d is created but I get an error at "checking debug dependencies for demo.cpp"

I believe demo.d is causing the errors, here is what it contains :

debug/demo.o: demo.cpp include/Candle/Lighting.hpp \
 include/Candle/Util.hpp include/Candle/LightSource.hpp
\t$(call print_info,Building $@)
\t$(CXX) -c $(CXXFLAGS) $(DBGCFLAGS) -o $@ $<

The other .d files have the same last 2 lines I have no idea if this is the expected output or not (but it looks strange to me).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.