From 0f3a020b5d89088036a58a1b219c3fc37e53bd59 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 15 Sep 2014 16:07:48 -0700 Subject: [PATCH] Working on getting particles/entities to work with deferred lighting; normalize normals from buffer. --- .../resources/shaders/directional_light.frag | 2 +- ...directional_light_cascaded_shadow_map.frag | 2 +- .../shaders/directional_light_shadow_map.frag | 2 +- interface/resources/shaders/simple.frag | 22 ++++++++++ interface/resources/shaders/simple.vert | 26 ++++++++++++ interface/src/Application.cpp | 20 ++++------ .../src/entities/RenderableBoxEntityItem.cpp | 6 ++- .../entities/RenderableModelEntityItem.cpp | 6 +-- .../entities/RenderableSphereEntityItem.cpp | 2 +- .../src/particles/ParticleTreeRenderer.cpp | 5 ++- .../src/renderer/DeferredLightingEffect.cpp | 40 +++++++++++++++++++ .../src/renderer/DeferredLightingEffect.h | 26 +++++++++++- 12 files changed, 135 insertions(+), 24 deletions(-) create mode 100644 interface/resources/shaders/simple.frag create mode 100644 interface/resources/shaders/simple.vert diff --git a/interface/resources/shaders/directional_light.frag b/interface/resources/shaders/directional_light.frag index 8ca10ce27e..da48149001 100644 --- a/interface/resources/shaders/directional_light.frag +++ b/interface/resources/shaders/directional_light.frag @@ -42,7 +42,7 @@ void main(void) { // get the normal from the map vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 normalizedNormal = normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0); + vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); // compute the base color based on OpenGL lighting model float diffuse = dot(normalizedNormal, gl_LightSource[0].position); diff --git a/interface/resources/shaders/directional_light_cascaded_shadow_map.frag b/interface/resources/shaders/directional_light_cascaded_shadow_map.frag index 980baf24f3..ac9c784d9a 100644 --- a/interface/resources/shaders/directional_light_cascaded_shadow_map.frag +++ b/interface/resources/shaders/directional_light_cascaded_shadow_map.frag @@ -56,7 +56,7 @@ void main(void) { // get the normal from the map vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 normalizedNormal = normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0); + vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); // average values from the shadow map float diffuse = dot(normalizedNormal, gl_LightSource[0].position); diff --git a/interface/resources/shaders/directional_light_shadow_map.frag b/interface/resources/shaders/directional_light_shadow_map.frag index ea2b9889d3..f1eaa20826 100644 --- a/interface/resources/shaders/directional_light_shadow_map.frag +++ b/interface/resources/shaders/directional_light_shadow_map.frag @@ -51,7 +51,7 @@ void main(void) { // get the normal from the map vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 normalizedNormal = normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0); + vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); // average values from the shadow map float diffuse = dot(normalizedNormal, gl_LightSource[0].position); diff --git a/interface/resources/shaders/simple.frag b/interface/resources/shaders/simple.frag new file mode 100644 index 0000000000..5c47e29d74 --- /dev/null +++ b/interface/resources/shaders/simple.frag @@ -0,0 +1,22 @@ +#version 120 + +// +// simple.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the interpolated normal +varying vec4 normal; + +void main(void) { + // set the diffuse, normal, specular data + gl_FragData[0] = vec4(gl_Color.rgb, 0.0); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/simple.vert b/interface/resources/shaders/simple.vert new file mode 100644 index 0000000000..c8fa0a9ebb --- /dev/null +++ b/interface/resources/shaders/simple.vert @@ -0,0 +1,26 @@ +#version 120 + +// +// simple.vert +// vertex shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the interpolated normal +varying vec4 normal; + +void main(void) { + // transform and store the normal for interpolation + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + + // pass along the diffuse color + gl_FrontColor = gl_Color; + + // use standard pipeline transform + gl_Position = ftransform(); +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 011df7757e..9d8f90c611 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2844,15 +2844,19 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { glutSolidSphere(originSphereRadius, 15, 15); glPopMatrix(); - // disable specular lighting for ground and voxels - glMaterialfv(GL_FRONT, GL_SPECULAR, NO_SPECULAR_COLOR); - // draw the audio reflector overlay { PerformanceTimer perfTimer("audio"); _audioReflector.render(); } + if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) { + PerformanceTimer perfTimer("buckyBalls"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "Application::displaySide() ... bucky balls..."); + _buckyBalls.render(); + } + // Draw voxels if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { PerformanceTimer perfTimer("voxels"); @@ -2869,13 +2873,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { _metavoxels.render(); } - if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) { - PerformanceTimer perfTimer("buckyBalls"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... bucky balls..."); - _buckyBalls.render(); - } - // render particles... if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) { PerformanceTimer perfTimer("particles"); @@ -2892,9 +2889,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { _entities.render(); } - // restore default, white specular - glMaterialfv(GL_FRONT, GL_SPECULAR, WORLD_SPECULAR_COLOR); - // render the ambient occlusion effect if enabled if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) { PerformanceTimer perfTimer("ambientOcclusion"); diff --git a/interface/src/entities/RenderableBoxEntityItem.cpp b/interface/src/entities/RenderableBoxEntityItem.cpp index 17cfbdcdaf..c39fb222bf 100644 --- a/interface/src/entities/RenderableBoxEntityItem.cpp +++ b/interface/src/entities/RenderableBoxEntityItem.cpp @@ -50,7 +50,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); glScalef(dimensions.x, dimensions.y, dimensions.z); - glutSolidCube(1.0f); + Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); glPopMatrix(); glPopMatrix(); } else { @@ -86,6 +86,8 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glColor3ub(getColor()[RED_INDEX], getColor()[GREEN_INDEX], getColor()[BLUE_INDEX]); + Application::getInstance()->getDeferredLightingEffect()->bindSimpleProgram(); + glPushMatrix(); glTranslatef(position.x, position.y, position.z); glm::vec3 axis = glm::axis(rotation); @@ -99,6 +101,8 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glPopMatrix(); glPopMatrix(); + Application::getInstance()->getDeferredLightingEffect()->releaseSimpleProgram(); + glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays glDisableClientState(GL_NORMAL_ARRAY); } diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 4347087287..6eb19bde31 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -125,7 +125,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); - glutWireCube(size); + Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size); glPopMatrix(); } } else { @@ -133,7 +133,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); - glutWireCube(size); + Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size); glPopMatrix(); } } @@ -142,7 +142,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); - glutWireCube(size); + Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size); glPopMatrix(); } } diff --git a/interface/src/entities/RenderableSphereEntityItem.cpp b/interface/src/entities/RenderableSphereEntityItem.cpp index d5286b0ab3..2ff725ad03 100644 --- a/interface/src/entities/RenderableSphereEntityItem.cpp +++ b/interface/src/entities/RenderableSphereEntityItem.cpp @@ -48,7 +48,7 @@ void RenderableSphereEntityItem::render(RenderArgs* args) { glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); glScalef(dimensions.x, dimensions.y, dimensions.z); - glutSolidSphere(0.5f, 15, 15); + Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(0.5f, 15, 15); glPopMatrix(); glPopMatrix(); }; diff --git a/interface/src/particles/ParticleTreeRenderer.cpp b/interface/src/particles/ParticleTreeRenderer.cpp index d9683405e2..4d47adedf0 100644 --- a/interface/src/particles/ParticleTreeRenderer.cpp +++ b/interface/src/particles/ParticleTreeRenderer.cpp @@ -11,6 +11,7 @@ #include +#include "Application.h" #include "InterfaceConfig.h" #include "ParticleTreeRenderer.h" @@ -112,7 +113,7 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg if (wantDebugSphere) { glPushMatrix(); glTranslatef(position.x, position.y, position.z); - glutWireSphere(radius, 15, 15); + Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(radius, 15, 15); glPopMatrix(); } @@ -120,7 +121,7 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg } else { glPushMatrix(); glTranslatef(position.x, position.y, position.z); - glutSolidSphere(radius, 15, 15); + Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(radius, 15, 15); glPopMatrix(); } } diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index ec925c18e8..68f1c7aa3d 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -19,6 +19,10 @@ #include "RenderUtil.h" void DeferredLightingEffect::init() { + _simpleProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/simple.vert"); + _simpleProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/simple.frag"); + _simpleProgram.link(); + loadLightProgram("shaders/directional_light.frag", _directionalLight, _directionalLightLocations); loadLightProgram("shaders/directional_light_shadow_map.frag", _directionalLightShadowMap, _directionalLightShadowMapLocations); @@ -26,6 +30,42 @@ void DeferredLightingEffect::init() { _directionalLightCascadedShadowMapLocations); } +void DeferredLightingEffect::bindSimpleProgram() { + Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true, true); + _simpleProgram.bind(); + glDisable(GL_BLEND); +} + +void DeferredLightingEffect::releaseSimpleProgram() { + glEnable(GL_BLEND); + _simpleProgram.release(); + Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false, false); +} + +void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int stacks) { + bindSimpleProgram(); + glutSolidSphere(radius, slices, stacks); + releaseSimpleProgram(); +} + +void DeferredLightingEffect::renderWireSphere(float radius, int slices, int stacks) { + bindSimpleProgram(); + glutWireSphere(radius, slices, stacks); + releaseSimpleProgram(); +} + +void DeferredLightingEffect::renderSolidCube(float size) { + bindSimpleProgram(); + glutSolidCube(size); + releaseSimpleProgram(); +} + +void DeferredLightingEffect::renderWireCube(float size) { + bindSimpleProgram(); + glutWireCube(size); + releaseSimpleProgram(); +} + void DeferredLightingEffect::prepare() { // clear the normal and specular buffers Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, false); diff --git a/interface/src/renderer/DeferredLightingEffect.h b/interface/src/renderer/DeferredLightingEffect.h index 46a4b4d7f6..1971019aca 100644 --- a/interface/src/renderer/DeferredLightingEffect.h +++ b/interface/src/renderer/DeferredLightingEffect.h @@ -24,6 +24,28 @@ public: void init(); + /// Returns a reference to a simple program suitable for rendering static + /// untextured geometry (such as that generated by glutSolidSphere, etc.) + ProgramObject& getSimpleProgram() { return _simpleProgram; } + + /// Sets up the state necessary to render static untextured geometry with the simple program. + void bindSimpleProgram(); + + /// Tears down the state necessary to render static untextured geometry with the simple program. + void releaseSimpleProgram(); + + //// Renders a solid sphere with the simple program. + void renderSolidSphere(float radius, int slices, int stacks); + + //// Renders a wireframe sphere with the simple program. + void renderWireSphere(float radius, int slices, int stacks); + + //// Renders a solid cube with the simple program. + void renderSolidCube(float size); + + //// Renders a wireframe cube with the simple program. + void renderWireCube(float size); + /// Adds an object to render after performing the deferred lighting for the current frame (e.g., a translucent object). void addPostLightingRenderable(PostLightingRenderable* renderable) { _postLightingRenderables.append(renderable); } @@ -43,7 +65,9 @@ private: }; static void loadLightProgram(const char* name, ProgramObject& program, LightLocations& locations); - + + ProgramObject _simpleProgram; + ProgramObject _directionalLight; LightLocations _directionalLightLocations; ProgramObject _directionalLightShadowMap;