Project

General

Profile

SO3Engine
SO3DeferredLightPointMaterialGenerator.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
26
27namespace SO3
28{
29
33
37
38Ogre::GpuProgramPtr SDeferredLightPointMaterialGenerator::GenerateVertexShader(SGBuffer* gbuffer, Ogre::uint32 permutationValue)
39{
40 Ogre::StringStream ss;
41
42 ss << "void SO3_DeferredLightPoint_vs(float4 Pos: POSITION," << std::endl;
43 ss << " out float4 oPos: POSITION," << std::endl;
44 ss << " out float4 oTexCoord : TEXCOORD0," << std::endl;
45 ss << " uniform float4x4 wvp" << std::endl;
46 ss << " )" << std::endl;
47 ss << "{" << std::endl;
48 ss << " float4 projPos = mul(wvp, Pos);" << std::endl;
49 ss << " oTexCoord = projPos;" << std::endl;
50 ss << " oPos = projPos;" << std::endl;
51 ss << "}" << std::endl;
52
53 // Prepare shader generation
54 Ogre::String programSource = ss.str();
55 Ogre::String programName = materialBaseName +"Shaders/Vertex/"+ gbuffer->GetName();
56
57#if SO3_DEBUG
58 // Show the generated vertex program in the log.
59 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(programSource, Ogre::LML_CRITICAL);
60#endif
61
62 // Create shader object
63 // TODO in another group than Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME?
64 Ogre::HighLevelGpuProgramPtr ptrProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(programName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", Ogre::GPT_VERTEX_PROGRAM);
65 ptrProgram->setSource(programSource);
66 ptrProgram->setParameter("entry_point", "SO3_DeferredLightPoint_vs");
67 ptrProgram->setParameter("profiles", "vs_1_1 arbvp1");
68
69 // Bind our function parameters to Ogre's related values.
70 const Ogre::GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters();
71 if (params->_findNamedConstantDefinition("wvp"))
72 params->setNamedAutoConstant("wvp", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
73
74 // Return light vertex shader
75 ptrProgram->load();
76 return Ogre::GpuProgramPtr(ptrProgram);
77}
78
79Ogre::GpuProgramPtr SDeferredLightPointMaterialGenerator::GenerateFragmentShader(SGBuffer* gbuffer, Ogre::uint32 permutationValue)
80{
81 Ogre::StringStream ss;
82
83 // Structures defines
85
86 //DirectX needs this to compensate for jitter
87 ss << "ps_4_0 float2 fixUV(float2 texCoord, float2 texSize)" << std::endl;
88 ss << "{" << std::endl;
89 ss << " return texCoord - (float2(0.5,0.5)/texSize);" << std::endl;
90 ss << "}" << std::endl;
91 ss << "float2 fixUV(float2 texCoord, float2 texSize)" << std::endl;
92 ss << "{" << std::endl;
93 ss << " return texCoord;" << std::endl;
94 ss << "}" << std::endl;
95
96 // Shadows
98 {
99 ss << "void checkShadow(samplerCUBE shadowMap," << std::endl;
100 ss << " float3 viewPos," << std::endl;
101 ss << " float4x4 invView," << std::endl;
102 ss << " float4x4 shadowViewProj," << std::endl;
103 ss << " float shadowFarClip," << std::endl;
104 ss << " float distanceFromLight)" << std::endl;
105 ss << "{" << std::endl;
106 ss << " float3 worldPos = mul(invView, float4(viewPos, 1)).xyz;" << std::endl;
107 ss << " float4 shadowProjPos = mul(shadowViewProj, float4(worldPos,1));" << std::endl;
108 ss << " shadowProjPos /= shadowProjPos.w;" << std::endl;
109 ss << " float3 shadowSampleTexCoord = shadowProjPos.xyz;" << std::endl;
110 ss << " float shadowDepth = texCUBE(shadowMap, shadowSampleTexCoord).r;" << std::endl;
111 ss << " float shadowDistance = shadowDepth * shadowFarClip;" << std::endl;
112 ss << " clip(shadowDistance - distanceFromLight + 0.1);" << std::endl;
113 ss << "}" << std::endl;
114 }
115
116 ss << "float4 SO3_DeferredLightPoint_ps(float4 projPos : TEXCOORD0," << std::endl;
117 ss << " " << gbuffer->GetGBufferCompositorPixelInputStructureTypeName() << " gBuffer," << std::endl; // Input parameters (list of mrts)
118 ss << " uniform float vpWidth," << std::endl;
119 ss << " uniform float vpHeight," << std::endl;
120 ss << " uniform float3 farCorner," << std::endl;
121 ss << " uniform float flip," << std::endl;
122 ss << " uniform float farClipDistance," << std::endl;
123
124 // Shadow parameters
126 {
127 ss << " uniform float4x4 invView," << std::endl;
128 ss << " uniform float4x4 shadowViewProjMat," << std::endl;
129 ss << " uniform sampler2D ShadowTex : register(s" << gbuffer->GetNumberMrt() << ")," << std::endl;
130 ss << " uniform float shadowFarClip," << std::endl;
131 }
132
133 // Attributes of light
134 ss << " uniform float4 lightDiffuseColor," << std::endl;
135 ss << " uniform float4 lightSpecularColor," << std::endl;
136 ss << " uniform float4 lightFalloff," << std::endl;
137 ss << " uniform float3 lightPos," << std::endl;
138 ss << " uniform float lightPower" << std::endl;
139 ss << " ) : COLOR " << std::endl;
140 ss << "{" << std::endl;
141 ss << " projPos /= projPos.w;" << std::endl;
142
143 // -1 is because generally +Y is down for textures but up for the screen
144 ss << " float2 texCoord = float2(projPos.x, projPos.y * -1 * flip) * 0.5 + 0.5;" << std::endl;
145
146 // Texture coordinate magic, this compensates for jitter
147 ss << " texCoord = fixUV(texCoord, float2(vpWidth, vpHeight));" << std::endl;
148 ss << " float3 ray = float3(projPos.x, projPos.y * flip, 1) * farCorner;" << std::endl;
149
150 // Attributes
151 ss << " float3 colour = gBuffer.GetDiffuse(texCoord);" << std::endl;
152 ss << " float specularity = gBuffer.GetShininess(texCoord);" << std::endl;
153 ss << " float distance = gBuffer.GetDepth(texCoord);" << std::endl;
154 ss << " float3 normal = gBuffer.GetNormal(texCoord);" << std::endl;
155
156 // Calculate position of texel in view space
157 ss << " float3 viewPos = normalize(ray)*distance*farClipDistance;" << std::endl;
158
159 // Calculate light direction and distance
160 ss << " float3 objToLightVec = lightPos - viewPos;" << std::endl;
161 ss << " float len_sq = dot(objToLightVec, objToLightVec);" << std::endl;
162 ss << " float len = sqrt(len_sq);" << std::endl;
163 ss << " float3 objToLightDir = objToLightVec/len;" << std::endl;
164
165 // Check texel in/out shadows
167 ss << " checkShadow(ShadowTex, viewPos, invView, shadowViewProjMat, shadowFarClip, len);" << std::endl;
168
169 // Calculate diffuse colour
170 ss << " float3 total_light_contrib;" << std::endl;
171 ss << " total_light_contrib = max(0.0,dot(objToLightDir, normal)) * lightDiffuseColor.rgb;" << std::endl;
172
173 // Calculate specular component
174 ss << " float3 viewDir = -normalize(viewPos);" << std::endl;
175 ss << " float3 h = normalize(viewDir + objToLightDir);" << std::endl;
176 ss << " float3 light_specular = pow(max(dot(normal, h), 0), specularity) * lightSpecularColor.rgb;" << std::endl;
177
178 // If GBuffer supports specular color, compute specular component using the material specular colour too.
180 ss << " light_specular *= gBuffer.GetSpecular(texCoord);" << std::endl;
181
182 // Add specular colour to total light contribution
183 ss << " total_light_contrib += light_specular;" << std::endl;
184
185 // Model based on quadratic attenuation
186 /*
187 // Clip, quadratic formula
188 ss << " float a = max(lightFalloff.w, 0.01);" << std::endl;
189 ss << " float b = lightFalloff.z;" << std::endl;
190 ss << " float c = lightFalloff.y;" << std::endl;
191 ss << " float threshold = 1 / (5 / 256.0);" << std::endl;
192 ss << " c -= threshold;" << std::endl;
193 ss << " float d = sqrt(b*b - 4*a*c);" << std::endl;
194 ss << " float outerRadius = (-b + d) / (2*a);" << std::endl;
195 ss << " outerRadius *= 1.1;" << std::endl;
196 ss << " clip(outerRadius - len);" << std::endl;
197
198 // Calculate attenuation
199 ss << " float constantAttenuation = lightFalloff.y;" << std::endl;
200 ss << " float linearAttenuation = lightFalloff.z / lightFalloff.x;" << std::endl;
201 ss << " float quadricAttenuation = lightFalloff.w / (lightFalloff.x * lightFalloff.x);" << std::endl;
202 ss << " float attenuation = 1 / dot(float3(constantAttenuation, linearAttenuation, quadricAttenuation), float3(1.0, len, len_sq));" << std::endl;
203 */
204
205 ss << " clip(lightFalloff.x);" << std::endl;
206 ss << " float attenuation = dot(lightFalloff.yzw, float3(1.0, len, len_sq));" << std::endl; // Simpler technique, no need to scale to range
207
208 // Final color
209 ss << " total_light_contrib *= 1-attenuation;" << std::endl;
210 ss << " total_light_contrib *= 2.0f * lightPower;" << std::endl; //default power is low
211 ss << " return float4(total_light_contrib*colour, 0.0);" << std::endl;
212 ss << "}" << std::endl;
213
214 // Prepare shader generation
215 Ogre::String programSource = ss.str();
216 Ogre::String programName = materialBaseName +"Shaders/Pixel/"+ gbuffer->GetName() + Ogre::StringConverter::toString(permutationValue);
217
218#if SO3_DEBUG
219 // Show the generated vertex program in the log.
220 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(programSource, Ogre::LML_CRITICAL);
221#endif
222
223 // Create shader object
224 // TODO in another group than Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME?
225 Ogre::HighLevelGpuProgramPtr ptrProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(programName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", Ogre::GPT_FRAGMENT_PROGRAM);
226 ptrProgram->setSource(programSource);
227 ptrProgram->setParameter("entry_point", "SO3_DeferredLightPoint_ps");
228 ptrProgram->setParameter("profiles", "ps_4_0 ps_2_x arbfp1");
229
230 // Bind our function parameters to Ogre's related values.
231 const Ogre::GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters();
232 if(Ogre::Root::getSingleton().getRenderSystem()->getName() != "OpenGL Rendering Subsystem")
233 {
234 if (params->_findNamedConstantDefinition("vpWidth"))
235 params->setNamedAutoConstant("vpWidth", Ogre::GpuProgramParameters::ACT_VIEWPORT_WIDTH);
236 if (params->_findNamedConstantDefinition("vpHeight"))
237 params->setNamedAutoConstant("vpHeight", Ogre::GpuProgramParameters::ACT_VIEWPORT_HEIGHT);
238 }
239 if (params->_findNamedConstantDefinition("flip"))
240 params->setNamedAutoConstant("flip", Ogre::GpuProgramParameters::ACT_RENDER_TARGET_FLIPPING);
241 if (params->_findNamedConstantDefinition("lightDiffuseColor"))
242 params->setNamedAutoConstant("lightDiffuseColor", Ogre::GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, 0);
243 if (params->_findNamedConstantDefinition("lightSpecularColor"))
244 params->setNamedAutoConstant("lightSpecularColor", Ogre::GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0);
245 if (params->_findNamedConstantDefinition("lightFalloff"))
246 params->setNamedAutoConstant("lightFalloff", Ogre::GpuProgramParameters::ACT_LIGHT_ATTENUATION, 0);
247 if (params->_findNamedConstantDefinition("lightPos"))
248 params->setNamedAutoConstant("lightPos", Ogre::GpuProgramParameters::ACT_LIGHT_POSITION_VIEW_SPACE, 0);
249 if (params->_findNamedConstantDefinition("lightPower"))
250 params->setNamedAutoConstant("lightPower", Ogre::GpuProgramParameters::ACT_LIGHT_POWER_SCALE, 0);
251 if (params->_findNamedConstantDefinition("farClipDistance"))
252 params->setNamedAutoConstant("farClipDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
253
254 // Shadows autoparams
256 {
257 if (params->_findNamedConstantDefinition("invView"))
258 params->setNamedAutoConstant("invView", Ogre::GpuProgramParameters::ACT_INVERSE_VIEW_MATRIX);
259 if (params->_findNamedConstantDefinition("shadowViewProjMat"))
260 params->setNamedAutoConstant("shadowViewProjMat", Ogre::GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX);
261 }
262
263 // Return compositor pixel shader
264 ptrProgram->load();
265 return Ogre::GpuProgramPtr(ptrProgram);
266}
267
268Ogre::MaterialPtr SDeferredLightPointMaterialGenerator::GenerateTemplateMaterial(SGBuffer* gbuffer, Ogre::uint32 permutationValue)
269{
270 Ogre::MaterialPtr matPtr = SDeferredLightMaterialGenerator::GenerateTemplateMaterial(gbuffer, permutationValue);
271 Ogre::Pass* ogrePass = matPtr->getTechnique(0)->getPass(0);
272 ogrePass->setSceneBlending(Ogre::SBT_ADD);
273 return matPtr;
274}
275
276}
std::string GetName() const
virtual Ogre::MaterialPtr GenerateTemplateMaterial(SGBuffer *gbuffer, Ogre::uint32 permutationValue)
virtual Ogre::GpuProgramPtr GenerateVertexShader(SGBuffer *gbuffer, Ogre::uint32 permutationValue)
virtual Ogre::GpuProgramPtr GenerateFragmentShader(SGBuffer *gbuffer, Ogre::uint32 permutationValue)
virtual Ogre::MaterialPtr GenerateTemplateMaterial(SGBuffer *gbuffer, Ogre::uint32 permutationValue)
Ogre::uint32 GetChannels()
Ogre::String GenerateGBufferCompositorPixelInputStructure()
unsigned int GetNumberMrt() const
Ogre::String GetGBufferCompositorPixelInputStructureTypeName()
const Ogre::String materialBaseName
Base name of materials generated by this.