From 0c7f1146b4a19b35aa5b2fedcad524cd7d011d37 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Wed, 31 Jan 2018 21:56:40 +0100 Subject: [PATCH 1/2] 1.0.1 Improve specular highlight for Blinn-Phong. Add attenuation to PBR. --- README.md | 2 +- em-build.sh | 15 +-- include/sre/impl/ShaderSource.inl | 91 ++++++++++++------- src/embedded_deps/light_phong_incl.glsl | 33 ++----- .../standard_blinn_phong_vert.glsl | 25 ++++- src/embedded_deps/standard_pbr_frag.glsl | 15 ++- src/embedded_deps/standard_pbr_vert.glsl | 24 ++++- src/sre/Camera.cpp | 4 +- src/sre/Shader.cpp | 3 + test/multiple-lights.cpp | 44 +++++++-- version-history.md | 1 + 11 files changed, 179 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 1738a5f1..a11a1827 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ sre provides: * GUI rendering (using Dear ImGui) * Emscripten support (allows cross compiling to HTML 5 + WebGL) * VR support + * Bump mapping To keep sre as simple and flexible as possible the following features are not a part of sre: * Scenegraphs * Deferred rendering - * Bump mapping * Shadowmap support * Dynamic particle systems diff --git a/em-build.sh b/em-build.sh index aac2c5ea..7a7196d9 100755 --- a/em-build.sh +++ b/em-build.sh @@ -8,7 +8,7 @@ fi source ${EMSDK}/emsdk_env.sh -for FILENAME in benchmark64k custom-mesh-layout gui hello-engine hello-engine-raw obj-viewer picking render-to-texture spheres spinning-cube spinning-primitives-tex sprite-example +for FILENAME in multiple-lights imgui-color-test pbr-test custom-mesh-layout-default-values imgui_demo multi-cameras particle-sprite particle-test polygon-offset-example spinning-sphere-cubemap sprite-test static_vertex_attribute texture-test do echo $FILENAME emcc -Iinclude src/imgui/imgui.cpp \ @@ -33,11 +33,12 @@ emcc -Iinclude src/imgui/imgui.cpp \ src/sre/SpriteAtlas.cpp \ src/sre/Inspector.cpp \ src/sre/Log.cpp \ - examples/$FILENAME.cpp \ - -O2 -std=c++14 -s FORCE_FILESYSTEM=1 -s TOTAL_MEMORY=33554432 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' --preload-file examples_data -s USE_SDL=2 -o html/$FILENAME.html + test/$FILENAME.cpp \ + -O2 -std=c++14 -s FORCE_FILESYSTEM=1 -s TOTAL_MEMORY=67108864 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' --preload-file test_data -s USE_SDL=2 -o html/$FILENAME.html done -for FILENAME in imgui-color-test pbr-test custom-mesh-layout-default-values imgui_demo multi-cameras multiple-lights particle-sprite particle-test polygon-offset-example spinning-sphere-cubemap sprite-test static_vertex_attribute texture-test + +for FILENAME in benchmark64k custom-mesh-layout gui hello-engine hello-engine-raw obj-viewer picking render-to-texture spheres spinning-cube spinning-primitives-tex sprite-example do echo $FILENAME emcc -Iinclude src/imgui/imgui.cpp \ @@ -62,6 +63,6 @@ emcc -Iinclude src/imgui/imgui.cpp \ src/sre/SpriteAtlas.cpp \ src/sre/Inspector.cpp \ src/sre/Log.cpp \ - test/$FILENAME.cpp \ - -O2 -std=c++14 -s FORCE_FILESYSTEM=1 -s TOTAL_MEMORY=67108864 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' --preload-file test_data -s USE_SDL=2 -o html/$FILENAME.html -done \ No newline at end of file + examples/$FILENAME.cpp \ + -O2 -std=c++14 -s FORCE_FILESYSTEM=1 -s TOTAL_MEMORY=33554432 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' --preload-file examples_data -s USE_SDL=2 -o html/$FILENAME.html +done diff --git a/include/sre/impl/ShaderSource.inl b/include/sre/impl/ShaderSource.inl index 1739c766..17f09066 100644 --- a/include/sre/impl/ShaderSource.inl +++ b/include/sre/impl/ShaderSource.inl @@ -84,36 +84,23 @@ void main(void) { vUV = uv; })"), std::make_pair("light_phong_incl.glsl",R"(uniform vec3 g_ambientLight; -uniform vec4 g_lightPosType[SI_LIGHTS]; +in vec4 vLightDir[SI_LIGHTS]; +#ifdef GL_ES +uniform highp vec4 g_lightColorRange[SI_LIGHTS]; +#else uniform vec4 g_lightColorRange[SI_LIGHTS]; +#endif uniform vec4 specularity; vec3 computeLight(vec3 wsPos, vec3 wsCameraPos, vec3 normal, out vec3 specularityOut){ specularityOut = vec3(0.0, 0.0, 0.0); vec3 lightColor = vec3(0.0,0.0,0.0); for (int i=0;i= lightRange){ - att = 0.0; - } else { - att = pow(1.0 - lightVectorLength / lightRange,1.5); // non physical range based attenuation - } - } else { + float att = vLightDir[i].w; + if (att <= 0.0){ continue; } - + vec3 lightDirection = normalize(vLightDir[i].xyz); // diffuse light float thisDiffuse = max(0.0,dot(lightDirection, normal)); if (thisDiffuse > 0.0){ @@ -122,11 +109,11 @@ vec3 computeLight(vec3 wsPos, vec3 wsCameraPos, vec3 normal, out vec3 specularit // specular light if (specularity.a > 0.0){ - vec3 H = normalize(lightDirection - normalize(wsPos - wsCameraPos)); + vec3 H = normalize(lightDirection + normalize(wsCameraPos - wsPos)); float nDotHV = dot(normal, H); if (nDotHV > 0.0){ float pf = pow(nDotHV, specularity.a); - specularityOut += specularity.rgb*pf; // white specular highlights + specularityOut += specularity.rgb * pf * att; // white specular highlights } } } @@ -243,10 +230,14 @@ in vec3 vNormal; #endif in vec2 vUV; in vec3 vWsPos; -in vec3 vLightDir[SI_LIGHTS]; +in vec4 vLightDir[SI_LIGHTS]; uniform vec3 g_ambientLight; +#ifdef GL_ES +uniform highp vec4 g_lightColorRange[SI_LIGHTS]; +#else uniform vec4 g_lightColorRange[SI_LIGHTS]; +#endif uniform vec4 color; uniform vec4 metallicRoughness; uniform vec4 g_cameraPos; @@ -381,7 +372,12 @@ void main(void) vec3 n = getNormal(); // Normal at surface point vec3 v = normalize(g_cameraPos.xyz - vWsPos.xyz); // Vector from surface point to camera for (int i=0;i= lightRange){ - att = 0.0; - } else { - att = pow(1.0 - lightVectorLength / lightRange,1.5); // non physical range based attenuation - } - } else { + float att = vLightDir[i].w; + if (att <= 0.0){ continue; } - + vec3 lightDirection = normalize(vLightDir[i].xyz); // diffuse light float thisDiffuse = max(0.0,dot(lightDirection, normal)); if (thisDiffuse > 0.0){ @@ -37,11 +24,11 @@ vec3 computeLight(vec3 wsPos, vec3 wsCameraPos, vec3 normal, out vec3 specularit // specular light if (specularity.a > 0.0){ - vec3 H = normalize(lightDirection - normalize(wsPos - wsCameraPos)); + vec3 H = normalize(lightDirection + normalize(wsCameraPos - wsPos)); float nDotHV = dot(normal, H); if (nDotHV > 0.0){ float pf = pow(nDotHV, specularity.a); - specularityOut += specularity.rgb*pf; // white specular highlights + specularityOut += specularity.rgb * pf * att; // white specular highlights } } } diff --git a/src/embedded_deps/standard_blinn_phong_vert.glsl b/src/embedded_deps/standard_blinn_phong_vert.glsl index 87c06496..527b20d8 100644 --- a/src/embedded_deps/standard_blinn_phong_vert.glsl +++ b/src/embedded_deps/standard_blinn_phong_vert.glsl @@ -14,11 +14,14 @@ out vec3 vWsPos; in vec4 color; out vec4 vColor; #endif +out vec4 vLightDir[SI_LIGHTS]; uniform mat4 g_model; uniform mat4 g_view; uniform mat4 g_projection; uniform mat3 g_model_it; +uniform vec4 g_lightPosType[SI_LIGHTS]; +uniform vec4 g_lightColorRange[SI_LIGHTS]; #pragma include "normalmap_incl.glsl" @@ -31,7 +34,27 @@ void main(void) { vNormal = normalize(g_model_it * normal); #endif vUV = uv.xy; - vWsPos = vWsPos.xyz; + vWsPos = wsPos.xyz; + for (int i=0;i lines = split(source, '\n'); + int includes = 0; for (auto& s : lines) { lineNumber++; @@ -102,6 +103,8 @@ namespace sre { errors.push_back(std::string("0:")+std::to_string(lineNumber)+" cannot find include file "+match+"##"+std::to_string(shaderType)); sstream << s << "\n"; } else { + includes++; + sstream << "#line "<<(includes*10000+1) <<"\n"; sstream << res << "\n"; sstream << "#line "< #include #include +#include using namespace sre; @@ -27,7 +28,8 @@ class MultipleLightsExample { camera.lookAt(eye,at, up); camera.setPerspectiveProjection(60,0.1f,100); - mesh = Mesh::create().withSphere().build(); + meshSphere = Mesh::create().withSphere().build(); + meshCube = Mesh::create().withCube().build(); for (int i=0;igetMaxSceneLights();i++){ worldLights.addLight(Light::create().withPointLight({0, 2,1}).withColor({1,1,1}).withRange(10).build()); @@ -47,6 +49,9 @@ class MultipleLightsExample { mat->setColor(color); time += deltaTime; + if (animatedObject){ + rot += deltaTime; + } } void render() { auto renderPass = RenderPass::create() @@ -56,11 +61,15 @@ class MultipleLightsExample { .build(); drawCross(renderPass,{2,2,2}); drawCross(renderPass,{-2,-2,-2}); - renderPass.draw(mesh, glm::eulerAngleY(time), mat); + + + renderPass.draw(drawSphere?meshSphere:meshCube, glm::eulerAngleY(rot), mat); ImGui::DragFloat3("Camera",&eye.x); ImGui::Checkbox("AnimatedLight",&animatedLight); ImGui::Checkbox("AnimatedCamera",&animatedCamera); + ImGui::Checkbox("AnimatedObject",&animatedObject); + if (animatedCamera){ eye = { sin(time*-0.2)*5.0f, @@ -82,6 +91,8 @@ class MultipleLightsExample { if (debugLight) { ImGui::DragFloat("DebugLightSize", &debugLightSize,0.1f,0,3); } + ImGui::Checkbox("Draw Sphere",&drawSphere); + // Show Label (with invisible window) for (int i=0;igetMaxSceneLights();i++){ auto l = worldLights.getLight(i); @@ -101,20 +112,33 @@ class MultipleLightsExample { ImGui::DragFloat3("Position", &(l->position.x)); ImGui::DragFloat3("Direction", &(l->direction.x)); ImGui::DragFloat("Range", &(l->range),1,0,30); - ImGui::TreePop(); } } if (ImGui::TreeNode("Material")){ - ImGui::DragFloat4("Specularity", &specularity.r,0.1,0,1); - mat->setSpecularity(specularity); + if (ImGui::Checkbox("BlinnPhong",&useBlinnPhong)){ + mat = useBlinnPhong?Shader::getStandardBlinnPhong()->createMaterial() : Shader::getStandardPBR()->createMaterial(); + } + if (useBlinnPhong){ + ImGui::DragFloat4("Specularity", &specularity.r,0.1,0,1); + mat->setSpecularity(specularity); + } else { + ImGui::DragFloat("Metallic", &metalRoughness.x,0.1,0,1); + ImGui::DragFloat("Roughness", &metalRoughness.y,0.1,0,1); + mat->setMetallicRoughness(metalRoughness); + } auto col = color.toLinear(); if (ImGui::ColorEdit3("Color", &(col.x))){ color.setFromLinear(col); } + ImGui::TreePop(); } + + static Inspector inspector; + inspector.update(); + inspector.gui(); } void drawCross(RenderPass& rp, glm::vec3 p, float size = 0.3f){ @@ -142,16 +166,24 @@ class MultipleLightsExample { Camera camera; std::shared_ptr mat; + bool useBlinnPhong = true; + glm::vec2 metalRoughness; Color specularity = Color(1,1,1,20); sre::Color color {1,1,1,1}; - std::shared_ptr mesh; + std::shared_ptr meshSphere; + std::shared_ptr meshCube; + + bool drawSphere = true; WorldLights worldLights; bool debugLight = true; bool animatedLight = true; bool animatedCamera = true; + bool animatedObject = true; + + float rot = 0; float debugLightSize = 0.2; float time = 0; diff --git a/version-history.md b/version-history.md index 3219c26d..45c2536a 100644 --- a/version-history.md +++ b/version-history.md @@ -1,5 +1,6 @@ ## Version history + * 1.0.1 Improve specular highlight for Blinn-Phong. Add attenuation to PBR. * 1.0.0 Physically based rendering. Profiler renamed to Inspector. Added shader specialization constants. Trimmed sprites. * 0.9.23 Add support for geometry and tesselation shaders. Fix MSVC compile error. * 0.9.22 OpenVR support (experimental). Queue draw calls (to better support simultaneous renderpasses). Make max scenelight count depends on Renderer::maxSceneLights. Optimize and clarify sprite batch order. From 173ca361e33c9a47217488c3752016d8b1465f59 Mon Sep 17 00:00:00 2001 From: Morten Nobel-Joergensen Date: Wed, 31 Jan 2018 22:04:37 +0100 Subject: [PATCH 2/2] 1.0.1 Version tick --- include/sre/Renderer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sre/Renderer.hpp b/include/sre/Renderer.hpp index 64a66446..7ab28e5d 100755 --- a/include/sre/Renderer.hpp +++ b/include/sre/Renderer.hpp @@ -65,7 +65,7 @@ namespace sre { ~Renderer(); static constexpr int sre_version_major = 1; static constexpr int sre_version_minor = 0; - static constexpr int sre_version_point = 0; + static constexpr int sre_version_point = 1; glm::ivec2 getWindowSize(); // Return the current size of the window