Project

General

Profile

SO3Engine
SO3DeferredLightSpotMaterialGenerator.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 SDeferredLightSpotMaterialGenerator::GenerateVertexShader(SGBuffer* gbuffer, Ogre::uint32 permutationValue)
39{
40 Ogre::StringStream ss;
41
42 ss << "void SO3_DeferredLightSpot_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_DeferredLightSpot_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 SDeferredLightSpotMaterialGenerator::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 // Shadow check
98 {
99 ss << "void checkShadow(sampler2D 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 << " float2 shadowSampleTexCoord = shadowProjPos.xy;" << std::endl;
110 ss << " float shadowDepth = tex2D(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 // cgc -entry SO3_DeferredLightSpot_ps -profile ps_4_0 -DIS_SHADOW_CASTER SO3_DeferredLightSpot_ps.cg
117 ss << "float4 SO3_DeferredLightSpot_ps(float4 projPos : TEXCOORD0," << std::endl;
118 ss << " " << gbuffer->GetGBufferCompositorPixelInputStructureTypeName() << " gBuffer," << std::endl; // Input parameters (list of mrts)
119 ss << " uniform float3 lightDir," << std::endl;
120 ss << " uniform float4 spotParams," << std::endl;
121 ss << " uniform float vpWidth," << std::endl;
122 ss << " uniform float vpHeight," << std::endl;
123 ss << " uniform float3 farCorner," << std::endl;
124 ss << " uniform float flip," << std::endl;
125 ss << " uniform float farClipDistance," << std::endl;
126
127 // Shadow parameters
129 {
130 ss << " uniform float4x4 invView," << std::endl;
131 ss << " uniform float4x4 shadowViewProjMat," << std::endl;
132 ss << " uniform sampler2D ShadowTex : register(s" << gbuffer->GetNumberMrt() << ")," << std::endl;
133 ss << " uniform float shadowFarClip," << std::endl;
134 }
135
136 // Attributes of light
137 ss << " uniform float4 lightDiffuseColor," << std::endl;
138 ss << " uniform float4 lightSpecularColor," << std::endl;
139 ss << " uniform float4 lightFalloff," << std::endl;
140 ss << " uniform float3 lightPos," << std::endl;
141 ss << " uniform float lightPower" << std::endl;
142 ss << " ) : COLOR" << std::endl;
143 ss << "{" << std::endl;
144
145 //None directional lights have some calculations to do in the beginning of the pixel shader
146 ss << " projPos /= projPos.w;" << std::endl;
147
148 // -1 is because generally +Y is down for textures but up for the screen
149 ss << " float2 texCoord = float2(projPos.x, projPos.y * -1 * flip) * 0.5 + 0.5;" << std::endl;
150
151 // Texture coordinate magic, this compensates for jitter
152 ss << " texCoord = fixUV(texCoord, float2(vpWidth, vpHeight));" << std::endl;
153 ss << " float3 ray = float3(projPos.x, projPos.y * flip, 1) * farCorner;" << std::endl;
154
155 // Attributes
156 ss << " float3 colour = gBuffer.GetDiffuse(texCoord);" << std::endl;
157 ss << " float specularity = gBuffer.GetShininess(texCoord);" << std::endl;
158 ss << " float distance = gBuffer.GetDepth(texCoord);" << std::endl;
159 ss << " float3 normal = gBuffer.GetNormal(texCoord);" << std::endl;
160
161 // Calculate position of texel in view space
162 ss << " float3 viewPos = normalize(ray)*distance*farClipDistance;" << std::endl;
163
164 // Calculate light direction and distance
165 ss << " float3 objToLightVec = lightPos - viewPos;" << std::endl;
166 ss << " float len_sq = dot(objToLightVec, objToLightVec);" << std::endl;
167 ss << " float len = sqrt(len_sq);" << std::endl;
168 ss << " float3 objToLightDir = objToLightVec/len;" << std::endl;
169
170 // In/out shadow comparison.
172 ss << " checkShadow(ShadowTex, viewPos, invView, shadowViewProjMat, shadowFarClip, len);" << std::endl;
173
174 // Calculate diffuse colour
175 ss << " float3 total_light_contrib;" << std::endl;
176 ss << " total_light_contrib = max(0.0, dot(objToLightDir, normal)) * lightDiffuseColor.rgb;" << std::endl;
177
178 // Calculate specular component
179 ss << " float3 viewDir = -normalize(viewPos);" << std::endl;
180 ss << " float3 h = normalize(viewDir + objToLightDir);" << std::endl;
181 ss << " float3 light_specular = pow(max(dot(normal, h), 0), specularity) * lightSpecularColor.rgb;" << std::endl;
182
183 // If GBuffer supports specular color, compute specular component using the material specular colour too.
185 ss << " light_specular *= gBuffer.GetSpecular(texCoord);" << std::endl;
186
187 // Add specular colour to total light contribution
188 ss << " total_light_contrib += light_specular;" << std::endl;
189
190 // Clip texels that are between the spot radius and the bounds of the cone geometry.
191 ss << " clip(lightFalloff.x - len);" << std::endl;
192
193 // Calculate attenuation
194 //ss << " float attenuation = dot(lightFalloff.yzw, float3(1.0, len, len_sq));" << std::endl;
195 ss << " float attenuation = 1 - (len_sq / (lightFalloff.x * lightFalloff.x));" << std::endl;
196 ss << " total_light_contrib *= attenuation;" << std::endl;
197
198 ss << " float spotlightAngle = saturate(dot(lightDir.xyz, -objToLightDir));" << std::endl;
199 // ss << " float spotFalloff = saturate((spotlightAngle - spotParams.x) / (min(spotParams.y, 179) - spotParams.x));" << std::endl;
200 ss << " float spotFalloff = saturate((spotlightAngle - spotParams.x) / (spotParams.y - spotParams.x));" << std::endl;
201 ss << " total_light_contrib *= 1-spotFalloff;" << std::endl;
202 ss << " total_light_contrib *= lightPower;" << std::endl;
203
204 ss << " return float4(total_light_contrib*colour, 0.0);" << std::endl;
205 ss << "}" << std::endl;
206
207 // Prepare shader generation
208 Ogre::String programSource = ss.str();
209 Ogre::String programName = materialBaseName +"Shaders/Pixel/"+ gbuffer->GetName() + Ogre::StringConverter::toString(permutationValue);
210
211#if SO3_DEBUG
212 // Show the generated vertex program in the log.
213 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(programSource, Ogre::LML_CRITICAL);
214#endif
215
216 // Create shader object
217 // TODO in another group than Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME?
218 Ogre::HighLevelGpuProgramPtr ptrProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(programName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", Ogre::GPT_FRAGMENT_PROGRAM);
219 ptrProgram->setSource(programSource);
220 ptrProgram->setParameter("entry_point", "SO3_DeferredLightSpot_ps");
221 ptrProgram->setParameter("profiles", "ps_4_0 ps_2_x arbfp1");
222
223 // Bind our function parameters to Ogre's related values.
224 const Ogre::GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters();
225 if(Ogre::Root::getSingleton().getRenderSystem()->getName() != "OpenGL Rendering Subsystem")
226 {
227 if (params->_findNamedConstantDefinition("vpWidth"))
228 params->setNamedAutoConstant("vpWidth", Ogre::GpuProgramParameters::ACT_VIEWPORT_WIDTH);
229 if (params->_findNamedConstantDefinition("vpHeight"))
230 params->setNamedAutoConstant("vpHeight", Ogre::GpuProgramParameters::ACT_VIEWPORT_HEIGHT);
231 }
232
233 if (params->_findNamedConstantDefinition("flip"))
234 params->setNamedAutoConstant("flip", Ogre::GpuProgramParameters::ACT_RENDER_TARGET_FLIPPING);
235 if (params->_findNamedConstantDefinition("lightDiffuseColor"))
236 params->setNamedAutoConstant("lightDiffuseColor", Ogre::GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, 0);
237 if (params->_findNamedConstantDefinition("lightSpecularColor"))
238 params->setNamedAutoConstant("lightSpecularColor", Ogre::GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0);
239 if (params->_findNamedConstantDefinition("lightFalloff"))
240 params->setNamedAutoConstant("lightFalloff", Ogre::GpuProgramParameters::ACT_LIGHT_ATTENUATION, 0);
241 if (params->_findNamedConstantDefinition("lightPos"))
242 params->setNamedAutoConstant("lightPos", Ogre::GpuProgramParameters::ACT_LIGHT_POSITION_VIEW_SPACE, 0);
243 if (params->_findNamedConstantDefinition("lightPower"))
244 params->setNamedAutoConstant("lightPower", Ogre::GpuProgramParameters::ACT_LIGHT_POWER_SCALE, 0);
245 if (params->_findNamedConstantDefinition("lightDir"))
246 params->setNamedAutoConstant("lightDir", Ogre::GpuProgramParameters::ACT_LIGHT_DIRECTION_VIEW_SPACE, 0);
247 if (params->_findNamedConstantDefinition("spotParams"))
248 params->setNamedAutoConstant("spotParams", Ogre::GpuProgramParameters::ACT_SPOTLIGHT_PARAMS, 0);
249 if (params->_findNamedConstantDefinition("farClipDistance"))
250 params->setNamedAutoConstant("farClipDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
251
252 // Shadow autoparams
254 {
255 if (params->_findNamedConstantDefinition("invView"))
256 params->setNamedAutoConstant("invView", Ogre::GpuProgramParameters::ACT_INVERSE_VIEW_MATRIX);
257
258 if (params->_findNamedConstantDefinition("shadowViewProjMat"))
259 params->setNamedAutoConstant("shadowViewProjMat", Ogre::GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX);
260 }
261
262 // Return compositor pixel shader
263 ptrProgram->load();
264 return Ogre::GpuProgramPtr(ptrProgram);
265}
266
267Ogre::MaterialPtr SDeferredLightSpotMaterialGenerator::GenerateTemplateMaterial(SGBuffer* gbuffer, Ogre::uint32 permutationValue)
268{
269 Ogre::MaterialPtr matPtr = SDeferredLightMaterialGenerator::GenerateTemplateMaterial(gbuffer, permutationValue);
270 Ogre::Pass* ogrePass = matPtr->getTechnique(0)->getPass(0);
271 ogrePass->setSceneBlending(Ogre::SBT_ADD);
272 return matPtr;
273}
274
275}
std::string GetName() const
virtual Ogre::MaterialPtr GenerateTemplateMaterial(SGBuffer *gbuffer, Ogre::uint32 permutationValue)
virtual Ogre::GpuProgramPtr GenerateVertexShader(SGBuffer *gbuffer, Ogre::uint32 permutationValue)
virtual Ogre::MaterialPtr GenerateTemplateMaterial(SGBuffer *gbuffer, Ogre::uint32 permutationValue)
virtual Ogre::GpuProgramPtr GenerateFragmentShader(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.