History

Instanced rendering, first pass

Brad Davis committed 11 years ago

Commit 8a703d01 parent ec8639417 files · +1140 −899Browse files

Showing the changes to libraries/render-utils/src/DeferredLightingEffect.cpp (1 of 17 files). Show all

Unified · Split

libraries/render-utils/src/DeferredLightingEffect.cpp+844−808
@@ -1,809 +1,845 @@
1//1//
2// DeferredLightingEffect.cpp2// DeferredLightingEffect.cpp
3// interface/src/renderer3// interface/src/renderer
4//4//
5// Created by Andrzej Kapolka on 9/11/14.5// Created by Andrzej Kapolka on 9/11/14.
6// Copyright 2014 High Fidelity, Inc.6// Copyright 2014 High Fidelity, Inc.
7//7//
8// Distributed under the Apache License, Version 2.0.8// Distributed under the Apache License, Version 2.0.
9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10//10//
11 11
12#include "DeferredLightingEffect.h"12#include "DeferredLightingEffect.h"
13 13
14#include <GLMHelpers.h>14#include <GLMHelpers.h>
15#include <PathUtils.h>15#include <PathUtils.h>
16#include <ViewFrustum.h>16#include <ViewFrustum.h>
17 17
18#include <gpu/Batch.h>18#include <gpu/Batch.h>
19#include <gpu/Context.h>19#include <gpu/Context.h>
20#include <gpu/StandardShaderLib.h>20#include <gpu/StandardShaderLib.h>
21 21
22#include "AbstractViewStateInterface.h"22#include "AbstractViewStateInterface.h"
23#include "GeometryCache.h"23#include "GeometryCache.h"
24#include "TextureCache.h"24#include "TextureCache.h"
25#include "FramebufferCache.h"25#include "FramebufferCache.h"
26 26
27 27
28#include "simple_vert.h"28#include "simple_vert.h"
29#include "simple_textured_frag.h"29#include "simple_textured_frag.h"
30#include "simple_textured_emisive_frag.h"30#include "simple_textured_emisive_frag.h"
31 31
32#include "deferred_light_vert.h"32#include "deferred_light_vert.h"
33#include "deferred_light_limited_vert.h"33#include "deferred_light_limited_vert.h"
34#include "deferred_light_spot_vert.h"34#include "deferred_light_spot_vert.h"
35 35
36#include "directional_light_frag.h"36#include "directional_light_frag.h"
37#include "directional_light_shadow_map_frag.h"37#include "directional_light_shadow_map_frag.h"
38#include "directional_light_cascaded_shadow_map_frag.h"38#include "directional_light_cascaded_shadow_map_frag.h"
39 39
40#include "directional_ambient_light_frag.h"40#include "directional_ambient_light_frag.h"
41#include "directional_ambient_light_shadow_map_frag.h"41#include "directional_ambient_light_shadow_map_frag.h"
42#include "directional_ambient_light_cascaded_shadow_map_frag.h"42#include "directional_ambient_light_cascaded_shadow_map_frag.h"
43 43
44#include "directional_skybox_light_frag.h"44#include "directional_skybox_light_frag.h"
45#include "directional_skybox_light_shadow_map_frag.h"45#include "directional_skybox_light_shadow_map_frag.h"
46#include "directional_skybox_light_cascaded_shadow_map_frag.h"46#include "directional_skybox_light_cascaded_shadow_map_frag.h"
47 47
48#include "point_light_frag.h"48#include "point_light_frag.h"
49#include "spot_light_frag.h"49#include "spot_light_frag.h"
50 50
51static const std::string glowIntensityShaderHandle = "glowIntensity";51static const std::string glowIntensityShaderHandle = "glowIntensity";
52 52
53struct LightLocations {53struct LightLocations {
54 int shadowDistances;54 int shadowDistances;
55 int shadowScale;55 int shadowScale;
56 int radius;56 int radius;
57 int ambientSphere;57 int ambientSphere;
58 int lightBufferUnit;58 int lightBufferUnit;
59 int atmosphereBufferUnit;59 int atmosphereBufferUnit;
60 int texcoordMat;60 int texcoordMat;
61 int coneParam;61 int coneParam;
62 int deferredTransformBuffer;62 int deferredTransformBuffer;
63};63};
64 64
65static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);65static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);
66 66
67 67
68gpu::PipelinePointer DeferredLightingEffect::getPipeline(SimpleProgramKey config) {68gpu::PipelinePointer DeferredLightingEffect::getPipeline(SimpleProgramKey config) {
69 auto it = _simplePrograms.find(config);69 auto it = _simplePrograms.find(config);
70 if (it != _simplePrograms.end()) {70 if (it != _simplePrograms.end()) {
71 return it.value();71 return it.value();
72 }72 }
73 73
74 auto state = std::make_shared<gpu::State>();74 auto state = std::make_shared<gpu::State>();
75 if (config.isCulled()) {75 if (config.isCulled()) {
76 state->setCullMode(gpu::State::CULL_BACK);76 state->setCullMode(gpu::State::CULL_BACK);
77 } else {77 } else {
78 state->setCullMode(gpu::State::CULL_NONE);78 state->setCullMode(gpu::State::CULL_NONE);
79 }79 }
80 state->setDepthTest(true, true, gpu::LESS_EQUAL);80 state->setDepthTest(true, true, gpu::LESS_EQUAL);
81 if (config.hasDepthBias()) {81 if (config.hasDepthBias()) {
82 state->setDepthBias(1.0f);82 state->setDepthBias(1.0f);
83 state->setDepthBiasSlopeScale(1.0f);83 state->setDepthBiasSlopeScale(1.0f);
84 }84 }
85 state->setBlendFunction(false,85 state->setBlendFunction(false,
86 gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,86 gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
87 gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);87 gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
88 88
89 gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;89 gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
90 gpu::PipelinePointer pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));90 gpu::PipelinePointer pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
91 _simplePrograms.insert(config, pipeline);91 _simplePrograms.insert(config, pipeline);
92 return pipeline;92 return pipeline;
93}93}
94 94
95void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {95void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
96 auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(simple_vert)));96 auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(simple_vert)));
97 auto PS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(simple_textured_frag)));97 auto PS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(simple_textured_frag)));
98 auto PSEmissive = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(simple_textured_emisive_frag)));98 auto PSEmissive = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(simple_textured_emisive_frag)));
99 99
100 _simpleShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS));100 _simpleShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS));
101 _emissiveShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PSEmissive));101 _emissiveShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PSEmissive));
102 102
103 gpu::Shader::BindingSet slotBindings;103 gpu::Shader::BindingSet slotBindings;
104 slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT));104 slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT));
105 gpu::Shader::makeProgram(*_simpleShader, slotBindings);105 gpu::Shader::makeProgram(*_simpleShader, slotBindings);
106 gpu::Shader::makeProgram(*_emissiveShader, slotBindings);106 gpu::Shader::makeProgram(*_emissiveShader, slotBindings);
107 107
108 _viewState = viewState;108 _viewState = viewState;
109 _directionalLightLocations = std::make_shared<LightLocations>();109 _directionalLightLocations = std::make_shared<LightLocations>();
110 _directionalLightShadowMapLocations = std::make_shared<LightLocations>();110 _directionalLightShadowMapLocations = std::make_shared<LightLocations>();
111 _directionalLightCascadedShadowMapLocations = std::make_shared<LightLocations>();111 _directionalLightCascadedShadowMapLocations = std::make_shared<LightLocations>();
112 _directionalAmbientSphereLightLocations = std::make_shared<LightLocations>();112 _directionalAmbientSphereLightLocations = std::make_shared<LightLocations>();
113 _directionalAmbientSphereLightShadowMapLocations = std::make_shared<LightLocations>();113 _directionalAmbientSphereLightShadowMapLocations = std::make_shared<LightLocations>();
114 _directionalAmbientSphereLightCascadedShadowMapLocations = std::make_shared<LightLocations>();114 _directionalAmbientSphereLightCascadedShadowMapLocations = std::make_shared<LightLocations>();
115 _directionalSkyboxLightLocations = std::make_shared<LightLocations>();115 _directionalSkyboxLightLocations = std::make_shared<LightLocations>();
116 _directionalSkyboxLightShadowMapLocations = std::make_shared<LightLocations>();116 _directionalSkyboxLightShadowMapLocations = std::make_shared<LightLocations>();
117 _directionalSkyboxLightCascadedShadowMapLocations = std::make_shared<LightLocations>();117 _directionalSkyboxLightCascadedShadowMapLocations = std::make_shared<LightLocations>();
118 _pointLightLocations = std::make_shared<LightLocations>();118 _pointLightLocations = std::make_shared<LightLocations>();
119 _spotLightLocations = std::make_shared<LightLocations>();119 _spotLightLocations = std::make_shared<LightLocations>();
120 120
121 loadLightProgram(deferred_light_vert, directional_light_frag, false, _directionalLight, _directionalLightLocations);121 loadLightProgram(deferred_light_vert, directional_light_frag, false, _directionalLight, _directionalLightLocations);
122 loadLightProgram(deferred_light_vert, directional_light_shadow_map_frag, false, _directionalLightShadowMap,122 loadLightProgram(deferred_light_vert, directional_light_shadow_map_frag, false, _directionalLightShadowMap,
123 _directionalLightShadowMapLocations);123 _directionalLightShadowMapLocations);
124 loadLightProgram(deferred_light_vert, directional_light_cascaded_shadow_map_frag, false, _directionalLightCascadedShadowMap,124 loadLightProgram(deferred_light_vert, directional_light_cascaded_shadow_map_frag, false, _directionalLightCascadedShadowMap,
125 _directionalLightCascadedShadowMapLocations);125 _directionalLightCascadedShadowMapLocations);
126 126
127 loadLightProgram(deferred_light_vert, directional_ambient_light_frag, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations);127 loadLightProgram(deferred_light_vert, directional_ambient_light_frag, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations);
128 loadLightProgram(deferred_light_vert, directional_ambient_light_shadow_map_frag, false, _directionalAmbientSphereLightShadowMap,128 loadLightProgram(deferred_light_vert, directional_ambient_light_shadow_map_frag, false, _directionalAmbientSphereLightShadowMap,
129 _directionalAmbientSphereLightShadowMapLocations);129 _directionalAmbientSphereLightShadowMapLocations);
130 loadLightProgram(deferred_light_vert, directional_ambient_light_cascaded_shadow_map_frag, false, _directionalAmbientSphereLightCascadedShadowMap,130 loadLightProgram(deferred_light_vert, directional_ambient_light_cascaded_shadow_map_frag, false, _directionalAmbientSphereLightCascadedShadowMap,
131 _directionalAmbientSphereLightCascadedShadowMapLocations);131 _directionalAmbientSphereLightCascadedShadowMapLocations);
132 132
133 loadLightProgram(deferred_light_vert, directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations);133 loadLightProgram(deferred_light_vert, directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations);
134 loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_map_frag, false, _directionalSkyboxLightShadowMap,134 loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_map_frag, false, _directionalSkyboxLightShadowMap,
135 _directionalSkyboxLightShadowMapLocations);135 _directionalSkyboxLightShadowMapLocations);
136 loadLightProgram(deferred_light_vert, directional_skybox_light_cascaded_shadow_map_frag, false, _directionalSkyboxLightCascadedShadowMap,136 loadLightProgram(deferred_light_vert, directional_skybox_light_cascaded_shadow_map_frag, false, _directionalSkyboxLightCascadedShadowMap,
137 _directionalSkyboxLightCascadedShadowMapLocations);137 _directionalSkyboxLightCascadedShadowMapLocations);
138 138
139 139
140 loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations);140 loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations);
141 loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations);141 loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations);
142 142
143 {143 {
144 //auto VSFS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();144 //auto VSFS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
145 //auto PSBlit = gpu::StandardShaderLib::getDrawTexturePS();145 //auto PSBlit = gpu::StandardShaderLib::getDrawTexturePS();
146 auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS);146 auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS);
147 gpu::Shader::makeProgram(*blitProgram);147 gpu::Shader::makeProgram(*blitProgram);
148 auto blitState = std::make_shared<gpu::State>();148 auto blitState = std::make_shared<gpu::State>();
149 blitState->setBlendFunction(true,149 blitState->setBlendFunction(true,
150 gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,150 gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
151 gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);151 gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
152 blitState->setColorWriteMask(true, true, true, false);152 blitState->setColorWriteMask(true, true, true, false);
153 _blitLightBuffer = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState));153 _blitLightBuffer = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState));
154 }154 }
155 155
156 // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light156 // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light
157 _globalLights.push_back(0);157 _globalLights.push_back(0);
158 _allocatedLights.push_back(std::make_shared<model::Light>());158 _allocatedLights.push_back(std::make_shared<model::Light>());
159 159
160 model::LightPointer lp = _allocatedLights[0];160 model::LightPointer lp = _allocatedLights[0];
161 161
162 lp->setDirection(-glm::vec3(1.0f, 1.0f, 1.0f));162 lp->setDirection(-glm::vec3(1.0f, 1.0f, 1.0f));
163 lp->setColor(glm::vec3(1.0f));163 lp->setColor(glm::vec3(1.0f));
164 lp->setIntensity(1.0f);164 lp->setIntensity(1.0f);
165 lp->setType(model::Light::SUN);165 lp->setType(model::Light::SUN);
166 lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset(_ambientLightMode % gpu::SphericalHarmonics::NUM_PRESET));166 lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset(_ambientLightMode % gpu::SphericalHarmonics::NUM_PRESET));
167}167}
168 168
169 169
170 170
171void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,171gpu::PipelinePointer DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,
172 bool emmisive, bool depthBias) {172 bool emmisive, bool depthBias) {
173 SimpleProgramKey config{textured, culled, emmisive, depthBias};173 SimpleProgramKey config{textured, culled, emmisive, depthBias};
174 batch.setPipeline(getPipeline(config));174 gpu::PipelinePointer pipeline = getPipeline(config);
175 175 batch.setPipeline(pipeline);
176 gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;176
177 int glowIntensity = program->getUniforms().findLocation("glowIntensity");177 gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
178 batch._glUniform1f(glowIntensity, 1.0f);178 int glowIntensity = program->getUniforms().findLocation("glowIntensity");
179 179 batch._glUniform1f(glowIntensity, 1.0f);
180 if (!config.isTextured()) {180
181 // If it is not textured, bind white texture and keep using textured pipeline181 if (!config.isTextured()) {
182 batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());182 // If it is not textured, bind white texture and keep using textured pipeline
183 }183 batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
184 184 }
185 batch.setResourceTexture(NORMAL_FITTING_MAP_SLOT, DependencyManager::get<TextureCache>()->getNormalFittingTexture());185
186}186 batch.setResourceTexture(NORMAL_FITTING_MAP_SLOT, DependencyManager::get<TextureCache>()->getNormalFittingTexture());
187 187 return pipeline;
188void DeferredLightingEffect::renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) {188}
189 bindSimpleProgram(batch);189
190 DependencyManager::get<GeometryCache>()->renderSphere(batch, radius, slices, stacks, color);190
191}191void DeferredLightingEffect::renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) {
192 192 bindSimpleProgram(batch);
193void DeferredLightingEffect::renderWireSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) {193 DependencyManager::get<GeometryCache>()->renderSphere(batch, radius, slices, stacks, color);
194 bindSimpleProgram(batch);194}
195 DependencyManager::get<GeometryCache>()->renderSphere(batch, radius, slices, stacks, color, false);195
196}196void DeferredLightingEffect::renderWireSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) {
197 197 bindSimpleProgram(batch);
198void DeferredLightingEffect::renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color) {198 DependencyManager::get<GeometryCache>()->renderSphere(batch, radius, slices, stacks, color, false);
199 bindSimpleProgram(batch);199}
200 DependencyManager::get<GeometryCache>()->renderSolidCube(batch, size, color);200
201}201uint32_t toCompactColor(const glm::vec4& color) {
202 202 uint32_t compactColor = ((int(color.x * 255.0f) & 0xFF)) |
203void DeferredLightingEffect::renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color) {203 ((int(color.y * 255.0f) & 0xFF) << 8) |
204 bindSimpleProgram(batch);204 ((int(color.z * 255.0f) & 0xFF) << 16) |
205 DependencyManager::get<GeometryCache>()->renderWireCube(batch, size, color);205 ((int(color.w * 255.0f) & 0xFF) << 24);
206}206 return compactColor;
207 207}
208void DeferredLightingEffect::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner,208
209 const glm::vec4& color) {209void DeferredLightingEffect::renderSolidCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color) {
210 bindSimpleProgram(batch);210 static const std::string INSTANCE_NAME = __FUNCTION__;
211 DependencyManager::get<GeometryCache>()->renderQuad(batch, minCorner, maxCorner, color);211 static const size_t TRANSFORM_BUFFER = 0;
212}212 static const size_t COLOR_BUFFER = 1;
213 213 {
214void DeferredLightingEffect::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,214 gpu::BufferPointer instanceTransformBuffer = batch.getNamedBuffer(INSTANCE_NAME, TRANSFORM_BUFFER);
215 const glm::vec4& color1, const glm::vec4& color2) {215 glm::mat4 xfmMat4;
216 bindSimpleProgram(batch);216 instanceTransformBuffer->append(xfm.getMatrix(xfmMat4));
217 DependencyManager::get<GeometryCache>()->renderLine(batch, p1, p2, color1, color2);217
218}218 gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(INSTANCE_NAME, COLOR_BUFFER);
219 219 auto compactColor = toCompactColor(color);
220void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color,220 instanceColorBuffer->append(compactColor);
221 float intensity) {221 }
222 addSpotLight(position, radius, color, intensity); 222
223}223 batch.setupNamedCalls(INSTANCE_NAME, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
224 224 auto pipeline = bindSimpleProgram(batch);
225void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color,225 auto location = pipeline->getProgram()->getUniforms().findLocation("Instanced");
226 float intensity, const glm::quat& orientation, float exponent, float cutoff) {226
227 227 batch._glUniform1i(location, 1);
228 unsigned int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size();228 DependencyManager::get<GeometryCache>()->renderSolidCubeInstances(batch, data._count,
229 if (lightID >= _allocatedLights.size()) {229 data._buffers[TRANSFORM_BUFFER], data._buffers[COLOR_BUFFER]);
230 _allocatedLights.push_back(std::make_shared<model::Light>());230 batch._glUniform1i(location, 0);
231 }231 });
232 model::LightPointer lp = _allocatedLights[lightID];232}
233 233
234 lp->setPosition(position);234void DeferredLightingEffect::renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color) {
235 lp->setMaximumRadius(radius);235 bindSimpleProgram(batch);
236 lp->setColor(color);236 DependencyManager::get<GeometryCache>()->renderSolidCube(batch, size, color);
237 lp->setIntensity(intensity);237}
238 //lp->setShowContour(quadraticAttenuation);238
239 239void DeferredLightingEffect::renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color) {
240 if (exponent == 0.0f && cutoff == PI) {240 bindSimpleProgram(batch);
241 lp->setType(model::Light::POINT);241 DependencyManager::get<GeometryCache>()->renderWireCube(batch, size, color);
242 _pointLights.push_back(lightID);242}
243 243
244 } else {244void DeferredLightingEffect::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner,
245 lp->setOrientation(orientation);245 const glm::vec4& color) {
246 lp->setSpotAngle(cutoff);246 bindSimpleProgram(batch);
247 lp->setSpotExponent(exponent);247 DependencyManager::get<GeometryCache>()->renderQuad(batch, minCorner, maxCorner, color);
248 lp->setType(model::Light::SPOT);248}
249 _spotLights.push_back(lightID);249
250 }250void DeferredLightingEffect::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
251}251 const glm::vec4& color1, const glm::vec4& color2) {
252 252 bindSimpleProgram(batch);
253void DeferredLightingEffect::prepare(RenderArgs* args) {253 DependencyManager::get<GeometryCache>()->renderLine(batch, p1, p2, color1, color2);
254 gpu::Batch batch;254}
255 batch.enableStereo(false);255
256 256void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color,
257 batch.setStateScissorRect(args->_viewport);257 float intensity) {
258 258 addSpotLight(position, radius, color, intensity);
259 auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();259}
260 260
261 batch.setFramebuffer(primaryFbo);261void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color,
262 // clear the normal and specular buffers262 float intensity, const glm::quat& orientation, float exponent, float cutoff) {
263 batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR1, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true);263
264 const float MAX_SPECULAR_EXPONENT = 128.0f;264 unsigned int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size();
265 batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR2, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT), true);265 if (lightID >= _allocatedLights.size()) {
266 266 _allocatedLights.push_back(std::make_shared<model::Light>());
267 args->_context->render(batch);267 }
268}268 model::LightPointer lp = _allocatedLights[lightID];
269 269
270gpu::FramebufferPointer _copyFBO;270 lp->setPosition(position);
271 271 lp->setMaximumRadius(radius);
272void DeferredLightingEffect::render(RenderArgs* args) {272 lp->setColor(color);
273 gpu::Batch batch;273 lp->setIntensity(intensity);
274 274 //lp->setShowContour(quadraticAttenuation);
275 // Allocate the parameters buffer used by all the deferred shaders275
276 if (!_deferredTransformBuffer[0]._buffer) {276 if (exponent == 0.0f && cutoff == PI) {
277 DeferredTransform parameters;277 lp->setType(model::Light::POINT);
278 _deferredTransformBuffer[0] = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(DeferredTransform), (const gpu::Byte*) &parameters));278 _pointLights.push_back(lightID);
279 _deferredTransformBuffer[1] = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(DeferredTransform), (const gpu::Byte*) &parameters));279
280 }280 } else {
281 281 lp->setOrientation(orientation);
282 // Framebuffer copy operations cannot function as multipass stereo operations. 282 lp->setSpotAngle(cutoff);
283 batch.enableStereo(false);283 lp->setSpotExponent(exponent);
284 284 lp->setType(model::Light::SPOT);
285 // perform deferred lighting, rendering to free fbo285 _spotLights.push_back(lightID);
286 auto framebufferCache = DependencyManager::get<FramebufferCache>();286 }
287 287}
288 QSize framebufferSize = framebufferCache->getFrameBufferSize();288
289 289void DeferredLightingEffect::prepare(RenderArgs* args) {
290 // binding the first framebuffer290 gpu::Batch batch;
291 _copyFBO = framebufferCache->getFramebuffer();291 batch.enableStereo(false);
292 batch.setFramebuffer(_copyFBO);292
293 293 batch.setStateScissorRect(args->_viewport);
294 // Clearing it294
295 batch.setViewportTransform(args->_viewport);295 auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
296 batch.setStateScissorRect(args->_viewport);296
297 batch.clearColorFramebuffer(_copyFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true);297 batch.setFramebuffer(primaryFbo);
298 298 // clear the normal and specular buffers
299 // BInd the G-Buffer surfaces299 batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR1, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true);
300 batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture());300 const float MAX_SPECULAR_EXPONENT = 128.0f;
301 batch.setResourceTexture(1, framebufferCache->getPrimaryNormalTexture());301 batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR2, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT), true);
302 batch.setResourceTexture(2, framebufferCache->getPrimarySpecularTexture());302
303 batch.setResourceTexture(3, framebufferCache->getPrimaryDepthTexture());303 args->_context->render(batch);
304 304}
305 // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport)305
306 auto monoViewport = args->_viewport;306gpu::FramebufferPointer _copyFBO;
307 float sMin = args->_viewport.x / (float)framebufferSize.width();307
308 float sWidth = args->_viewport.z / (float)framebufferSize.width();308void DeferredLightingEffect::render(RenderArgs* args) {
309 float tMin = args->_viewport.y / (float)framebufferSize.height();309 gpu::Batch batch;
310 float tHeight = args->_viewport.w / (float)framebufferSize.height();310
311 311 // Allocate the parameters buffer used by all the deferred shaders
312 // The view frustum is the mono frustum base312 if (!_deferredTransformBuffer[0]._buffer) {
313 auto viewFrustum = args->_viewFrustum;313 DeferredTransform parameters;
314 314 _deferredTransformBuffer[0] = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(DeferredTransform), (const gpu::Byte*) &parameters));
315 // Eval the mono projection315 _deferredTransformBuffer[1] = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(DeferredTransform), (const gpu::Byte*) &parameters));
316 mat4 monoProjMat;316 }
317 viewFrustum->evalProjectionMatrix(monoProjMat);317
318 318 // Framebuffer copy operations cannot function as multipass stereo operations.
319 // The mono view transform319 batch.enableStereo(false);
320 Transform monoViewTransform;320
321 viewFrustum->evalViewTransform(monoViewTransform);321 // perform deferred lighting, rendering to free fbo
322 322 auto framebufferCache = DependencyManager::get<FramebufferCache>();
323 // THe mono view matrix coming from the mono view transform323
324 glm::mat4 monoViewMat;324 QSize framebufferSize = framebufferCache->getFrameBufferSize();
325 monoViewTransform.getMatrix(monoViewMat);325
326 326 // binding the first framebuffer
327 // Running in stero ?327 _copyFBO = framebufferCache->getFramebuffer();
328 bool isStereo = args->_context->isStereo();328 batch.setFramebuffer(_copyFBO);
329 int numPasses = 1;329
330 330 // Clearing it
331 mat4 projMats[2];331 batch.setViewportTransform(args->_viewport);
332 Transform viewTransforms[2];332 batch.setStateScissorRect(args->_viewport);
333 ivec4 viewports[2];333 batch.clearColorFramebuffer(_copyFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true);
334 vec4 clipQuad[2];334
335 vec2 screenBottomLeftCorners[2];335 // BInd the G-Buffer surfaces
336 vec2 screenTopRightCorners[2];336 batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture());
337 vec4 fetchTexcoordRects[2];337 batch.setResourceTexture(1, framebufferCache->getPrimaryNormalTexture());
338 338 batch.setResourceTexture(2, framebufferCache->getPrimarySpecularTexture());
339 DeferredTransform deferredTransforms[2];339 batch.setResourceTexture(3, framebufferCache->getPrimaryDepthTexture());
340 auto geometryCache = DependencyManager::get<GeometryCache>();340
341 341 // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport)
342 if (isStereo) {342 auto monoViewport = args->_viewport;
343 numPasses = 2;343 float sMin = args->_viewport.x / (float)framebufferSize.width();
344 344 float sWidth = args->_viewport.z / (float)framebufferSize.width();
345 mat4 eyeViews[2];345 float tMin = args->_viewport.y / (float)framebufferSize.height();
346 args->_context->getStereoProjections(projMats);346 float tHeight = args->_viewport.w / (float)framebufferSize.height();
347 args->_context->getStereoViews(eyeViews);347
348 348 // The view frustum is the mono frustum base
349 float halfWidth = 0.5 * sWidth;349 auto viewFrustum = args->_viewFrustum;
350 350
351 for (int i = 0; i < numPasses; i++) {351 // Eval the mono projection
352 // In stereo, the 2 sides are layout side by side in the mono viewport and their width is half352 mat4 monoProjMat;
353 int sideWidth = monoViewport.z >> 1;353 viewFrustum->evalProjectionMatrix(monoProjMat);
354 viewports[i] = ivec4(monoViewport.x + (i * sideWidth), monoViewport.y, sideWidth, monoViewport.w);354
355 355 // The mono view transform
356 deferredTransforms[i].projection = projMats[i];356 Transform monoViewTransform;
357 357 viewFrustum->evalViewTransform(monoViewTransform);
358
359 // THe mono view matrix coming from the mono view transform
360 glm::mat4 monoViewMat;
361 monoViewTransform.getMatrix(monoViewMat);
362
363 // Running in stero ?
364 bool isStereo = args->_context->isStereo();
365 int numPasses = 1;
366
367 mat4 projMats[2];
368 Transform viewTransforms[2];
369 ivec4 viewports[2];
370 vec4 clipQuad[2];
371 vec2 screenBottomLeftCorners[2];
372 vec2 screenTopRightCorners[2];
373 vec4 fetchTexcoordRects[2];
374
375 DeferredTransform deferredTransforms[2];
376 auto geometryCache = DependencyManager::get<GeometryCache>();
377
378 if (isStereo) {
379 numPasses = 2;
380
381 mat4 eyeViews[2];
382 args->_context->getStereoProjections(projMats);
383 args->_context->getStereoViews(eyeViews);
384
385 float halfWidth = 0.5 * sWidth;
386
387 for (int i = 0; i < numPasses; i++) {
388 // In stereo, the 2 sides are layout side by side in the mono viewport and their width is half
389 int sideWidth = monoViewport.z >> 1;
390 viewports[i] = ivec4(monoViewport.x + (i * sideWidth), monoViewport.y, sideWidth, monoViewport.w);
391
392 deferredTransforms[i].projection = projMats[i];
393
358 auto sideViewMat = eyeViews[i] * monoViewMat;394 auto sideViewMat = eyeViews[i] * monoViewMat;
359 viewTransforms[i].evalFromRawMatrix(sideViewMat);395 viewTransforms[i].evalFromRawMatrix(sideViewMat);
360 deferredTransforms[i].viewInverse = sideViewMat;396 deferredTransforms[i].viewInverse = sideViewMat;
361 397
362 deferredTransforms[i].stereoSide = (i == 0 ? -1.0f : 1.0f);398 deferredTransforms[i].stereoSide = (i == 0 ? -1.0f : 1.0f);
363 399
364 clipQuad[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight);400 clipQuad[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight);
365 screenBottomLeftCorners[i] = glm::vec2(-1.0f + i * 1.0f, -1.0f);401 screenBottomLeftCorners[i] = glm::vec2(-1.0f + i * 1.0f, -1.0f);
366 screenTopRightCorners[i] = glm::vec2(i * 1.0f, 1.0f);402 screenTopRightCorners[i] = glm::vec2(i * 1.0f, 1.0f);
367 403
368 fetchTexcoordRects[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight);404 fetchTexcoordRects[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight);
369 }405 }
370 } else {406 } else {
371 407
372 viewports[0] = monoViewport;408 viewports[0] = monoViewport;
373 projMats[0] = monoProjMat;409 projMats[0] = monoProjMat;
374 410
375 deferredTransforms[0].projection = monoProjMat;411 deferredTransforms[0].projection = monoProjMat;
376 412
377 deferredTransforms[0].viewInverse = monoViewMat;413 deferredTransforms[0].viewInverse = monoViewMat;
378 viewTransforms[0] = monoViewTransform;414 viewTransforms[0] = monoViewTransform;
379 415
380 deferredTransforms[0].stereoSide = 0.0f;416 deferredTransforms[0].stereoSide = 0.0f;
381 417
382 clipQuad[0] = glm::vec4(sMin, tMin, sWidth, tHeight);418 clipQuad[0] = glm::vec4(sMin, tMin, sWidth, tHeight);
383 screenBottomLeftCorners[0] = glm::vec2(-1.0f, -1.0f);419 screenBottomLeftCorners[0] = glm::vec2(-1.0f, -1.0f);
384 screenTopRightCorners[0] = glm::vec2(1.0f, 1.0f);420 screenTopRightCorners[0] = glm::vec2(1.0f, 1.0f);
385 421
386 fetchTexcoordRects[0] = glm::vec4(sMin, tMin, sWidth, tHeight);422 fetchTexcoordRects[0] = glm::vec4(sMin, tMin, sWidth, tHeight);
387 }423 }
388 424
389 auto eyePoint = viewFrustum->getPosition();425 auto eyePoint = viewFrustum->getPosition();
390 float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft());426 float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft());
391 427
392 428
393 for (int side = 0; side < numPasses; side++) {429 for (int side = 0; side < numPasses; side++) {
394 // Render in this side's viewport430 // Render in this side's viewport
395 batch.setViewportTransform(viewports[side]);431 batch.setViewportTransform(viewports[side]);
396 batch.setStateScissorRect(viewports[side]);432 batch.setStateScissorRect(viewports[side]);
397 433
398 // Sync and Bind the correct DeferredTransform ubo434 // Sync and Bind the correct DeferredTransform ubo
399 _deferredTransformBuffer[side]._buffer->setSubData(0, sizeof(DeferredTransform), (const gpu::Byte*) &deferredTransforms[side]);435 _deferredTransformBuffer[side]._buffer->setSubData(0, sizeof(DeferredTransform), (const gpu::Byte*) &deferredTransforms[side]);
400 batch.setUniformBuffer(_directionalLightLocations->deferredTransformBuffer, _deferredTransformBuffer[side]);436 batch.setUniformBuffer(_directionalLightLocations->deferredTransformBuffer, _deferredTransformBuffer[side]);
401 437
402 glm::vec2 topLeft(-1.0f, -1.0f);438 glm::vec2 topLeft(-1.0f, -1.0f);
403 glm::vec2 bottomRight(1.0f, 1.0f);439 glm::vec2 bottomRight(1.0f, 1.0f);
404 glm::vec2 texCoordTopLeft(clipQuad[side].x, clipQuad[side].y);440 glm::vec2 texCoordTopLeft(clipQuad[side].x, clipQuad[side].y);
405 glm::vec2 texCoordBottomRight(clipQuad[side].x + clipQuad[side].z, clipQuad[side].y + clipQuad[side].w);441 glm::vec2 texCoordBottomRight(clipQuad[side].x + clipQuad[side].z, clipQuad[side].y + clipQuad[side].w);
406 442
407 // First Global directional light and ambient pass443 // First Global directional light and ambient pass
408 {444 {
409 bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap());445 bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap());
410 446
411 auto& program = _directionalLight;447 auto& program = _directionalLight;
412 LightLocationsPtr locations = _directionalLightLocations;448 LightLocationsPtr locations = _directionalLightLocations;
413 449
414 // TODO: At some point bring back the shadows...450 // TODO: At some point bring back the shadows...
415 // Setup the global directional pass pipeline451 // Setup the global directional pass pipeline
416 {452 {
417 if (useSkyboxCubemap) {453 if (useSkyboxCubemap) {
418 program = _directionalSkyboxLight;454 program = _directionalSkyboxLight;
419 locations = _directionalSkyboxLightLocations;455 locations = _directionalSkyboxLightLocations;
420 } else if (_ambientLightMode > -1) {456 } else if (_ambientLightMode > -1) {
421 program = _directionalAmbientSphereLight;457 program = _directionalAmbientSphereLight;
422 locations = _directionalAmbientSphereLightLocations;458 locations = _directionalAmbientSphereLightLocations;
423 }459 }
424 batch.setPipeline(program);460 batch.setPipeline(program);
425 }461 }
426 462
427 { // Setup the global lighting463 { // Setup the global lighting
428 auto globalLight = _allocatedLights[_globalLights.front()];464 auto globalLight = _allocatedLights[_globalLights.front()];
429 465
430 if (locations->ambientSphere >= 0) {466 if (locations->ambientSphere >= 0) {
431 gpu::SphericalHarmonics sh = globalLight->getAmbientSphere();467 gpu::SphericalHarmonics sh = globalLight->getAmbientSphere();
432 if (useSkyboxCubemap && _skybox->getCubemap()->getIrradiance()) {468 if (useSkyboxCubemap && _skybox->getCubemap()->getIrradiance()) {
433 sh = (*_skybox->getCubemap()->getIrradiance());469 sh = (*_skybox->getCubemap()->getIrradiance());
434 }470 }
435 for (int i =0; i <gpu::SphericalHarmonics::NUM_COEFFICIENTS; i++) {471 for (int i =0; i <gpu::SphericalHarmonics::NUM_COEFFICIENTS; i++) {
436 batch._glUniform4fv(locations->ambientSphere + i, 1, (const float*) (&sh) + i * 4);472 batch._glUniform4fv(locations->ambientSphere + i, 1, (const float*) (&sh) + i * 4);
437 }473 }
438 }474 }
439 475
440 if (useSkyboxCubemap) {476 if (useSkyboxCubemap) {
441 batch.setResourceTexture(5, _skybox->getCubemap());477 batch.setResourceTexture(5, _skybox->getCubemap());
442 }478 }
443 479
444 if (locations->lightBufferUnit >= 0) {480 if (locations->lightBufferUnit >= 0) {
445 batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer());481 batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer());
446 }482 }
447 483
448 if (_atmosphere && (locations->atmosphereBufferUnit >= 0)) {484 if (_atmosphere && (locations->atmosphereBufferUnit >= 0)) {
449 batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer());485 batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer());
450 }486 }
451 }487 }
452 488
453 {489 {
454 batch.setModelTransform(Transform());490 batch.setModelTransform(Transform());
455 batch.setProjectionTransform(glm::mat4());491 batch.setProjectionTransform(glm::mat4());
456 batch.setViewTransform(Transform());492 batch.setViewTransform(Transform());
457 493
458 glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);494 glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);
459 geometryCache->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color);495 geometryCache->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color);
460 }496 }
461 497
462 if (useSkyboxCubemap) {498 if (useSkyboxCubemap) {
463 batch.setResourceTexture(5, nullptr);499 batch.setResourceTexture(5, nullptr);
464 }500 }
465 }501 }
466 502
467 auto texcoordMat = glm::mat4();503 auto texcoordMat = glm::mat4();
468 /* texcoordMat[0] = glm::vec4(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f);504 /* texcoordMat[0] = glm::vec4(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f);
469 texcoordMat[1] = glm::vec4(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f);505 texcoordMat[1] = glm::vec4(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f);
470 */ texcoordMat[0] = glm::vec4(fetchTexcoordRects[side].z / 2.0f, 0.0f, 0.0f, fetchTexcoordRects[side].x + fetchTexcoordRects[side].z / 2.0f);506 */ texcoordMat[0] = glm::vec4(fetchTexcoordRects[side].z / 2.0f, 0.0f, 0.0f, fetchTexcoordRects[side].x + fetchTexcoordRects[side].z / 2.0f);
471 texcoordMat[1] = glm::vec4(0.0f, fetchTexcoordRects[side].w / 2.0f, 0.0f, fetchTexcoordRects[side].y + fetchTexcoordRects[side].w / 2.0f);507 texcoordMat[1] = glm::vec4(0.0f, fetchTexcoordRects[side].w / 2.0f, 0.0f, fetchTexcoordRects[side].y + fetchTexcoordRects[side].w / 2.0f);
472 texcoordMat[2] = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f);508 texcoordMat[2] = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f);
473 texcoordMat[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);509 texcoordMat[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
474 510
475 // enlarge the scales slightly to account for tesselation511 // enlarge the scales slightly to account for tesselation
476 const float SCALE_EXPANSION = 0.05f;512 const float SCALE_EXPANSION = 0.05f;
477 513
478 514
479 batch.setProjectionTransform(projMats[side]);515 batch.setProjectionTransform(projMats[side]);
480 batch.setViewTransform(viewTransforms[side]);516 batch.setViewTransform(viewTransforms[side]);
481 517
482 // Splat Point lights518 // Splat Point lights
483 if (!_pointLights.empty()) {519 if (!_pointLights.empty()) {
484 batch.setPipeline(_pointLight);520 batch.setPipeline(_pointLight);
485 521
486 batch._glUniformMatrix4fv(_pointLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat));522 batch._glUniformMatrix4fv(_pointLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat));
487 523
488 for (auto lightID : _pointLights) {524 for (auto lightID : _pointLights) {
489 auto& light = _allocatedLights[lightID];525 auto& light = _allocatedLights[lightID];
490 // IN DEBUG: light->setShowContour(true);526 // IN DEBUG: light->setShowContour(true);
491 if (_pointLightLocations->lightBufferUnit >= 0) {527 if (_pointLightLocations->lightBufferUnit >= 0) {
492 batch.setUniformBuffer(_pointLightLocations->lightBufferUnit, light->getSchemaBuffer());528 batch.setUniformBuffer(_pointLightLocations->lightBufferUnit, light->getSchemaBuffer());
493 }529 }
494 530
495 float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);531 float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
496 // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume,532 // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume,
497 // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working...533 // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working...
498 if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) {534 if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) {
499 Transform model;535 Transform model;
500 model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f));536 model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f));
501 batch.setModelTransform(model);537 batch.setModelTransform(model);
502 batch.setViewTransform(Transform());538 batch.setViewTransform(Transform());
503 batch.setProjectionTransform(glm::mat4());539 batch.setProjectionTransform(glm::mat4());
504 540
505 glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);541 glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);
506 DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color);542 DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color);
507 543
508 batch.setProjectionTransform(projMats[side]);544 batch.setProjectionTransform(projMats[side]);
509 batch.setViewTransform(viewTransforms[side]);545 batch.setViewTransform(viewTransforms[side]);
510 } else {546 } else {
511 Transform model;547 Transform model;
512 model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z));548 model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z));
513 batch.setModelTransform(model);549 batch.setModelTransform(model);
514 geometryCache->renderSphere(batch, expandedRadius, 32, 32, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));550 geometryCache->renderSphere(batch, expandedRadius, 32, 32, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
515 }551 }
516 }552 }
517 }553 }
518 554
519 // Splat spot lights555 // Splat spot lights
520 if (!_spotLights.empty()) {556 if (!_spotLights.empty()) {
521 batch.setPipeline(_spotLight);557 batch.setPipeline(_spotLight);
522 558
523 batch._glUniformMatrix4fv(_spotLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat));559 batch._glUniformMatrix4fv(_spotLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat));
524 560
525 for (auto lightID : _spotLights) {561 for (auto lightID : _spotLights) {
526 auto light = _allocatedLights[lightID];562 auto light = _allocatedLights[lightID];
527 // IN DEBUG: light->setShowContour(true);563 // IN DEBUG: light->setShowContour(true);
528 564
529 batch.setUniformBuffer(_spotLightLocations->lightBufferUnit, light->getSchemaBuffer());565 batch.setUniformBuffer(_spotLightLocations->lightBufferUnit, light->getSchemaBuffer());
530 566
531 auto eyeLightPos = eyePoint - light->getPosition();567 auto eyeLightPos = eyePoint - light->getPosition();
532 auto eyeHalfPlaneDistance = glm::dot(eyeLightPos, light->getDirection());568 auto eyeHalfPlaneDistance = glm::dot(eyeLightPos, light->getDirection());
533 569
534 const float TANGENT_LENGTH_SCALE = 0.666f;570 const float TANGENT_LENGTH_SCALE = 0.666f;
535 glm::vec4 coneParam(light->getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * light->getSpotAngle()), 1.0f);571 glm::vec4 coneParam(light->getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * light->getSpotAngle()), 1.0f);
536 572
537 float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);573 float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
538 // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume,574 // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume,
539 // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working...575 // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working...
540 if ((eyeHalfPlaneDistance > -nearRadius) &&576 if ((eyeHalfPlaneDistance > -nearRadius) &&
541 (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius)) {577 (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius)) {
542 coneParam.w = 0.0f;578 coneParam.w = 0.0f;
543 batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));579 batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
544 580
545 Transform model;581 Transform model;
546 model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f));582 model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f));
547 batch.setModelTransform(model);583 batch.setModelTransform(model);
548 batch.setViewTransform(Transform());584 batch.setViewTransform(Transform());
549 batch.setProjectionTransform(glm::mat4());585 batch.setProjectionTransform(glm::mat4());
550 586
551 glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);587 glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);
552 DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color);588 DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color);
553 589
554 batch.setProjectionTransform( projMats[side]);590 batch.setProjectionTransform( projMats[side]);
555 batch.setViewTransform(viewTransforms[side]);591 batch.setViewTransform(viewTransforms[side]);
556 } else {592 } else {
557 coneParam.w = 1.0f;593 coneParam.w = 1.0f;
558 batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));594 batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
559 595
560 Transform model;596 Transform model;
561 model.setTranslation(light->getPosition());597 model.setTranslation(light->getPosition());
562 model.postRotate(light->getOrientation());598 model.postRotate(light->getOrientation());
563 model.postScale(glm::vec3(expandedRadius, expandedRadius, expandedRadius));599 model.postScale(glm::vec3(expandedRadius, expandedRadius, expandedRadius));
564 600
565 batch.setModelTransform(model);601 batch.setModelTransform(model);
566 auto mesh = getSpotLightMesh();602 auto mesh = getSpotLightMesh();
567 603
568 batch.setIndexBuffer(mesh->getIndexBuffer());604 batch.setIndexBuffer(mesh->getIndexBuffer());
569 batch.setInputBuffer(0, mesh->getVertexBuffer());605 batch.setInputBuffer(0, mesh->getVertexBuffer());
570 batch.setInputFormat(mesh->getVertexFormat());606 batch.setInputFormat(mesh->getVertexFormat());
571 607
572 auto& part = mesh->getPartBuffer().get<model::Mesh::Part>();608 auto& part = mesh->getPartBuffer().get<model::Mesh::Part>();
573 609
574 batch.drawIndexed(model::Mesh::topologyToPrimitive(part._topology), part._numIndices, part._startIndex);610 batch.drawIndexed(model::Mesh::topologyToPrimitive(part._topology), part._numIndices, part._startIndex);
575 }611 }
576 }612 }
577 }613 }
578 }614 }
579 615
580 // Probably not necessary in the long run because the gpu layer would unbound this texture if used as render target616 // Probably not necessary in the long run because the gpu layer would unbound this texture if used as render target
581 batch.setResourceTexture(0, nullptr);617 batch.setResourceTexture(0, nullptr);
582 batch.setResourceTexture(1, nullptr);618 batch.setResourceTexture(1, nullptr);
583 batch.setResourceTexture(2, nullptr);619 batch.setResourceTexture(2, nullptr);
584 batch.setResourceTexture(3, nullptr);620 batch.setResourceTexture(3, nullptr);
585 batch.setUniformBuffer(_directionalLightLocations->deferredTransformBuffer, nullptr);621 batch.setUniformBuffer(_directionalLightLocations->deferredTransformBuffer, nullptr);
586 622
587 args->_context->render(batch);623 args->_context->render(batch);
588 624
589 // End of the Lighting pass625 // End of the Lighting pass
590 if (!_pointLights.empty()) {626 if (!_pointLights.empty()) {
591 _pointLights.clear();627 _pointLights.clear();
592 }628 }
593 if (!_spotLights.empty()) {629 if (!_spotLights.empty()) {
594 _spotLights.clear();630 _spotLights.clear();
595 }631 }
596}632}
597 633
598 634
599void DeferredLightingEffect::copyBack(RenderArgs* args) {635void DeferredLightingEffect::copyBack(RenderArgs* args) {
600 gpu::Batch batch;636 gpu::Batch batch;
601 batch.enableStereo(false);637 batch.enableStereo(false);
602 auto framebufferCache = DependencyManager::get<FramebufferCache>();638 auto framebufferCache = DependencyManager::get<FramebufferCache>();
603 QSize framebufferSize = framebufferCache->getFrameBufferSize();639 QSize framebufferSize = framebufferCache->getFrameBufferSize();
604 640
605 // TODO why doesn't this blit work? It only seems to affect a small area below the rear view mirror.641 // TODO why doesn't this blit work? It only seems to affect a small area below the rear view mirror.
606 // auto destFbo = framebufferCache->getPrimaryFramebuffer();642 // auto destFbo = framebufferCache->getPrimaryFramebuffer();
607 auto destFbo = framebufferCache->getPrimaryFramebufferDepthColor();643 auto destFbo = framebufferCache->getPrimaryFramebufferDepthColor();
608// gpu::Vec4i vp = args->_viewport;644// gpu::Vec4i vp = args->_viewport;
609// batch.blit(_copyFBO, vp, framebufferCache->getPrimaryFramebuffer(), vp);645// batch.blit(_copyFBO, vp, framebufferCache->getPrimaryFramebuffer(), vp);
610 batch.setFramebuffer(destFbo);646 batch.setFramebuffer(destFbo);
611 batch.setViewportTransform(args->_viewport);647 batch.setViewportTransform(args->_viewport);
612 batch.setProjectionTransform(glm::mat4());648 batch.setProjectionTransform(glm::mat4());
613 batch.setViewTransform(Transform());649 batch.setViewTransform(Transform());
614 {650 {
615 float sMin = args->_viewport.x / (float)framebufferSize.width();651 float sMin = args->_viewport.x / (float)framebufferSize.width();
616 float sWidth = args->_viewport.z / (float)framebufferSize.width();652 float sWidth = args->_viewport.z / (float)framebufferSize.width();
617 float tMin = args->_viewport.y / (float)framebufferSize.height();653 float tMin = args->_viewport.y / (float)framebufferSize.height();
618 float tHeight = args->_viewport.w / (float)framebufferSize.height();654 float tHeight = args->_viewport.w / (float)framebufferSize.height();
619 Transform model;655 Transform model;
620 batch.setPipeline(_blitLightBuffer);656 batch.setPipeline(_blitLightBuffer);
621 model.setTranslation(glm::vec3(sMin, tMin, 0.0));657 model.setTranslation(glm::vec3(sMin, tMin, 0.0));
622 model.setScale(glm::vec3(sWidth, tHeight, 1.0));658 model.setScale(glm::vec3(sWidth, tHeight, 1.0));
623 batch.setModelTransform(model);659 batch.setModelTransform(model);
624 }660 }
625 661
626 batch.setResourceTexture(0, _copyFBO->getRenderBuffer(0));662 batch.setResourceTexture(0, _copyFBO->getRenderBuffer(0));
627 batch.draw(gpu::TRIANGLE_STRIP, 4);663 batch.draw(gpu::TRIANGLE_STRIP, 4);
628 664
629 args->_context->render(batch);665 args->_context->render(batch);
630 framebufferCache->releaseFramebuffer(_copyFBO);666 framebufferCache->releaseFramebuffer(_copyFBO);
631}667}
632 668
633void DeferredLightingEffect::setupTransparent(RenderArgs* args, int lightBufferUnit) {669void DeferredLightingEffect::setupTransparent(RenderArgs* args, int lightBufferUnit) {
634 auto globalLight = _allocatedLights[_globalLights.front()];670 auto globalLight = _allocatedLights[_globalLights.front()];
635 args->_batch->setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer());671 args->_batch->setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer());
636}672}
637 673
638static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {674static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {
639 auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(vertSource)));675 auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(vertSource)));
640 auto PS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fragSource)));676 auto PS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fragSource)));
641 677
642 gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS));678 gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS));
643 679
644 gpu::Shader::BindingSet slotBindings;680 gpu::Shader::BindingSet slotBindings;
645 slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0));681 slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0));
646 slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1));682 slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1));
647 slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2));683 slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2));
648 slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), 3));684 slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), 3));
649 slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), 4));685 slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), 4));
650 slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), 5));686 slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), 5));
651 const int LIGHT_GPU_SLOT = 3;687 const int LIGHT_GPU_SLOT = 3;
652 slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT));688 slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT));
653 const int ATMOSPHERE_GPU_SLOT = 4;689 const int ATMOSPHERE_GPU_SLOT = 4;
654 slotBindings.insert(gpu::Shader::Binding(std::string("atmosphereBufferUnit"), ATMOSPHERE_GPU_SLOT));690 slotBindings.insert(gpu::Shader::Binding(std::string("atmosphereBufferUnit"), ATMOSPHERE_GPU_SLOT));
655 691
656 slotBindings.insert(gpu::Shader::Binding(std::string("deferredTransformBuffer"), DeferredLightingEffect::DEFERRED_TRANSFORM_BUFFER_SLOT));692 slotBindings.insert(gpu::Shader::Binding(std::string("deferredTransformBuffer"), DeferredLightingEffect::DEFERRED_TRANSFORM_BUFFER_SLOT));
657 693
658 gpu::Shader::makeProgram(*program, slotBindings);694 gpu::Shader::makeProgram(*program, slotBindings);
659 695
660 locations->shadowDistances = program->getUniforms().findLocation("shadowDistances");696 locations->shadowDistances = program->getUniforms().findLocation("shadowDistances");
661 locations->shadowScale = program->getUniforms().findLocation("shadowScale");697 locations->shadowScale = program->getUniforms().findLocation("shadowScale");
662 698
663 locations->radius = program->getUniforms().findLocation("radius");699 locations->radius = program->getUniforms().findLocation("radius");
664 locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00");700 locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00");
665 701
666 locations->texcoordMat = program->getUniforms().findLocation("texcoordMat");702 locations->texcoordMat = program->getUniforms().findLocation("texcoordMat");
667 locations->coneParam = program->getUniforms().findLocation("coneParam");703 locations->coneParam = program->getUniforms().findLocation("coneParam");
668 704
669 locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer");705 locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer");
670 locations->atmosphereBufferUnit = program->getBuffers().findLocation("atmosphereBufferUnit");706 locations->atmosphereBufferUnit = program->getBuffers().findLocation("atmosphereBufferUnit");
671 locations->deferredTransformBuffer = program->getBuffers().findLocation("deferredTransformBuffer");707 locations->deferredTransformBuffer = program->getBuffers().findLocation("deferredTransformBuffer");
672 708
673 auto state = std::make_shared<gpu::State>();709 auto state = std::make_shared<gpu::State>();
674 if (lightVolume) {710 if (lightVolume) {
675 state->setCullMode(gpu::State::CULL_BACK);711 state->setCullMode(gpu::State::CULL_BACK);
676 712
677 // No need for z test since the depth buffer is not bound state->setDepthTest(true, false, gpu::LESS_EQUAL);713 // No need for z test since the depth buffer is not bound state->setDepthTest(true, false, gpu::LESS_EQUAL);
678 // TODO: We should bind the true depth buffer both as RT and texture for the depth test714 // TODO: We should bind the true depth buffer both as RT and texture for the depth test
679 // TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases715 // TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases
680 state->setDepthClampEnable(true);716 state->setDepthClampEnable(true);
681 717
682 // additive blending718 // additive blending
683 state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);719 state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
684 } else {720 } else {
685 state->setCullMode(gpu::State::CULL_BACK);721 state->setCullMode(gpu::State::CULL_BACK);
686 }722 }
687 pipeline.reset(gpu::Pipeline::create(program, state));723 pipeline.reset(gpu::Pipeline::create(program, state));
688 724
689}725}
690 726
691void DeferredLightingEffect::setAmbientLightMode(int preset) {727void DeferredLightingEffect::setAmbientLightMode(int preset) {
692 if ((preset >= 0) && (preset < gpu::SphericalHarmonics::NUM_PRESET)) {728 if ((preset >= 0) && (preset < gpu::SphericalHarmonics::NUM_PRESET)) {
693 _ambientLightMode = preset;729 _ambientLightMode = preset;
694 auto light = _allocatedLights.front();730 auto light = _allocatedLights.front();
695 light->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset(preset % gpu::SphericalHarmonics::NUM_PRESET));731 light->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset(preset % gpu::SphericalHarmonics::NUM_PRESET));
696 } else {732 } else {
697 // force to preset 0733 // force to preset 0
698 setAmbientLightMode(0);734 setAmbientLightMode(0);
699 }735 }
700}736}
701 737
702void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity, float ambientIntensity) {738void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity, float ambientIntensity) {
703 auto light = _allocatedLights.front();739 auto light = _allocatedLights.front();
704 light->setDirection(direction);740 light->setDirection(direction);
705 light->setColor(diffuse);741 light->setColor(diffuse);
706 light->setIntensity(intensity);742 light->setIntensity(intensity);
707 light->setAmbientIntensity(ambientIntensity);743 light->setAmbientIntensity(ambientIntensity);
708}744}
709 745
710void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) {746void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) {
711 _skybox = skybox;747 _skybox = skybox;
712}748}
713 749
714model::MeshPointer DeferredLightingEffect::getSpotLightMesh() {750model::MeshPointer DeferredLightingEffect::getSpotLightMesh() {
715 if (!_spotLightMesh) {751 if (!_spotLightMesh) {
716 _spotLightMesh = std::make_shared<model::Mesh>();752 _spotLightMesh = std::make_shared<model::Mesh>();
717 753
718 int slices = 32;754 int slices = 32;
719 int rings = 3;755 int rings = 3;
720 int vertices = 2 + rings * slices;756 int vertices = 2 + rings * slices;
721 int originVertex = vertices - 2;757 int originVertex = vertices - 2;
722 int capVertex = vertices - 1;758 int capVertex = vertices - 1;
723 int verticesSize = vertices * 3 * sizeof(float);759 int verticesSize = vertices * 3 * sizeof(float);
724 int indices = 3 * slices * (1 + 1 + 2 * (rings -1));760 int indices = 3 * slices * (1 + 1 + 2 * (rings -1));
725 int ringFloatOffset = slices * 3;761 int ringFloatOffset = slices * 3;
726 762
727 763
728 float* vertexData = new float[verticesSize];764 float* vertexData = new float[verticesSize];
729 float* vertexRing0 = vertexData;765 float* vertexRing0 = vertexData;
730 float* vertexRing1 = vertexRing0 + ringFloatOffset;766 float* vertexRing1 = vertexRing0 + ringFloatOffset;
731 float* vertexRing2 = vertexRing1 + ringFloatOffset;767 float* vertexRing2 = vertexRing1 + ringFloatOffset;
732 768
733 for (int i = 0; i < slices; i++) {769 for (int i = 0; i < slices; i++) {
734 float theta = TWO_PI * i / slices;770 float theta = TWO_PI * i / slices;
735 auto cosin = glm::vec2(cosf(theta), sinf(theta));771 auto cosin = glm::vec2(cosf(theta), sinf(theta));
736 772
737 *(vertexRing0++) = cosin.x;773 *(vertexRing0++) = cosin.x;
738 *(vertexRing0++) = cosin.y;774 *(vertexRing0++) = cosin.y;
739 *(vertexRing0++) = 0.0f;775 *(vertexRing0++) = 0.0f;
740 776
741 *(vertexRing1++) = cosin.x;777 *(vertexRing1++) = cosin.x;
742 *(vertexRing1++) = cosin.y;778 *(vertexRing1++) = cosin.y;
743 *(vertexRing1++) = 0.33f;779 *(vertexRing1++) = 0.33f;
744 780
745 *(vertexRing2++) = cosin.x;781 *(vertexRing2++) = cosin.x;
746 *(vertexRing2++) = cosin.y;782 *(vertexRing2++) = cosin.y;
747 *(vertexRing2++) = 0.66f;783 *(vertexRing2++) = 0.66f;
748 }784 }
749 785
750 *(vertexRing2++) = 0.0f;786 *(vertexRing2++) = 0.0f;
751 *(vertexRing2++) = 0.0f;787 *(vertexRing2++) = 0.0f;
752 *(vertexRing2++) = -1.0f;788 *(vertexRing2++) = -1.0f;
753 789
754 *(vertexRing2++) = 0.0f;790 *(vertexRing2++) = 0.0f;
755 *(vertexRing2++) = 0.0f;791 *(vertexRing2++) = 0.0f;
756 *(vertexRing2++) = 1.0f;792 *(vertexRing2++) = 1.0f;
757 793
758 _spotLightMesh->setVertexBuffer(gpu::BufferView(new gpu::Buffer(verticesSize, (gpu::Byte*) vertexData), gpu::Element::VEC3F_XYZ));794 _spotLightMesh->setVertexBuffer(gpu::BufferView(new gpu::Buffer(verticesSize, (gpu::Byte*) vertexData), gpu::Element::VEC3F_XYZ));
759 delete[] vertexData;795 delete[] vertexData;
760 796
761 gpu::uint16* indexData = new gpu::uint16[indices];797 gpu::uint16* indexData = new gpu::uint16[indices];
762 gpu::uint16* index = indexData;798 gpu::uint16* index = indexData;
763 for (int i = 0; i < slices; i++) {799 for (int i = 0; i < slices; i++) {
764 *(index++) = originVertex;800 *(index++) = originVertex;
765 801
766 int s0 = i;802 int s0 = i;
767 int s1 = ((i + 1) % slices);803 int s1 = ((i + 1) % slices);
768 *(index++) = s0;804 *(index++) = s0;
769 *(index++) = s1;805 *(index++) = s1;
770 806
771 int s2 = s0 + slices;807 int s2 = s0 + slices;
772 int s3 = s1 + slices;808 int s3 = s1 + slices;
773 *(index++) = s1;809 *(index++) = s1;
774 *(index++) = s0;810 *(index++) = s0;
775 *(index++) = s2;811 *(index++) = s2;
776 812
777 *(index++) = s1;813 *(index++) = s1;
778 *(index++) = s2;814 *(index++) = s2;
779 *(index++) = s3;815 *(index++) = s3;
780 816
781 int s4 = s2 + slices;817 int s4 = s2 + slices;
782 int s5 = s3 + slices;818 int s5 = s3 + slices;
783 *(index++) = s3;819 *(index++) = s3;
784 *(index++) = s2;820 *(index++) = s2;
785 *(index++) = s4;821 *(index++) = s4;
786 822
787 *(index++) = s3;823 *(index++) = s3;
788 *(index++) = s4;824 *(index++) = s4;
789 *(index++) = s5;825 *(index++) = s5;
790 826
791 827
792 *(index++) = s5;828 *(index++) = s5;
793 *(index++) = s4;829 *(index++) = s4;
794 *(index++) = capVertex;830 *(index++) = capVertex;
795 }831 }
796 832
797 _spotLightMesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(sizeof(unsigned short) * indices, (gpu::Byte*) indexData), gpu::Element::INDEX_UINT16));833 _spotLightMesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(sizeof(unsigned short) * indices, (gpu::Byte*) indexData), gpu::Element::INDEX_UINT16));
798 delete[] indexData;834 delete[] indexData;
799 835
800 model::Mesh::Part part(0, indices, 0, model::Mesh::TRIANGLES);836 model::Mesh::Part part(0, indices, 0, model::Mesh::TRIANGLES);
801 //DEBUG: model::Mesh::Part part(0, indices, 0, model::Mesh::LINE_STRIP);837 //DEBUG: model::Mesh::Part part(0, indices, 0, model::Mesh::LINE_STRIP);
802 838
803 _spotLightMesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(sizeof(part), (gpu::Byte*) &part), gpu::Element::PART_DRAWCALL));839 _spotLightMesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(sizeof(part), (gpu::Byte*) &part), gpu::Element::PART_DRAWCALL));
804 840
805 _spotLightMesh->makeBufferStream();841 _spotLightMesh->makeBufferStream();
806 }842 }
807 return _spotLightMesh;843 return _spotLightMesh;
808}844}
809 845