Project

General

Profile

SO3Engine
SO3DeferredLightDirectionalMaterialGenerator.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 SDeferredLightDirectionalMaterialGenerator::GenerateVertexShader(SGBuffer* gbuffer, Ogre::uint32 permutationValue)
39{
40 Ogre::StringStream ss;
41
42 ss << "void SO3_DeferredLightDirectional_vs(float4 Pos: POSITION," << std::endl;
43 ss << " out float4 oPos: POSITION," << std::endl;
44 ss << " out float2 oTexCoord: TEXCOORD0," << std::endl;
45 ss << " out float3 oRay : TEXCOORD1," << std::endl;
46 ss << " uniform float3 farCorner," << std::endl;
47 ss << " uniform float flip" << std::endl;
48 ss << ")" << std::endl;
49 ss << "{" << std::endl;
50
51 // Clean up inaccuracies
52 ss << " Pos.xy = sign(Pos.xy);" << std::endl;
53
54 // View space
55 ss << " oPos = float4(Pos.xy, 0, 1);" << std::endl;
56 ss << " oPos.y *= flip;" << std::endl;
57
58 // Image-space
59 ss << " oTexCoord.x = 0.5 * (1 + Pos.x);" << std::endl;
60 ss << " oTexCoord.y = 0.5 * (1 - Pos.y);" << std::endl;
61
62 // This ray will be interpolated and will be the ray from the camera
63 // to the far clip plane, per pixel
64 ss << " oRay = farCorner * float3(Pos.xy, 1);" << std::endl;
65 ss << "}" << std::endl;
66
67
68 // Prepare shader generation
69 Ogre::String programSource = ss.str();
70 Ogre::String programName = materialBaseName +"Shaders/Vertex/"+ gbuffer->GetName();
71
72#if SO3_DEBUG
73 // Show the generated vertex program in the log.
74 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(programSource, Ogre::LML_CRITICAL);
75#endif
76
77 // Create shader object
78 // TODO in another group than Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME?
79 Ogre::HighLevelGpuProgramPtr ptrProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(programName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", Ogre::GPT_VERTEX_PROGRAM);
80 ptrProgram->setSource(programSource);
81 ptrProgram->setParameter("entry_point", "SO3_DeferredLightDirectional_vs");
82 ptrProgram->setParameter("profiles", "vs_1_1 arbvp1");
83
84 // Bind our function parameters to Ogre's related values.
85 const Ogre::GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters();
86
87 if (params->_findNamedConstantDefinition("flip"))
88 params->setNamedAutoConstant("flip", Ogre::GpuProgramParameters::ACT_RENDER_TARGET_FLIPPING);
89
90 if (params->_findNamedConstantDefinition("farCorner"))
91 params->setNamedConstant("farCorner", Ogre::Vector3::UNIT_SCALE);
92
93 // Return light vertex shader
94 ptrProgram->load();
95 return Ogre::GpuProgramPtr(ptrProgram);
96}
97
98Ogre::GpuProgramPtr SDeferredLightDirectionalMaterialGenerator::GenerateFragmentShader(SGBuffer* gbuffer, Ogre::uint32 permutationValue)
99{
100 Ogre::StringStream ss;
101
102 // Structures defines
104
105 // Shadows
107 {
108 ss << "void checkShadow(sampler2D shadowMap," << std::endl;
109 ss << " float3 viewPos," << std::endl;
110 ss << " float4x4 invView," << std::endl;
111 ss << " float4x4 shadowViewProj," << std::endl;
112 ss << " float shadowFarClip," << std::endl;
113 ss << " float3 shadowCamPos)" << std::endl;
114 ss << "{" << std::endl;
115 ss << " float3 worldPos = mul(invView, float4(viewPos, 1)).xyz;" << std::endl;
116 ss << " float distanceFromLight = length(shadowCamPos-worldPos);" << std::endl;
117 ss << " float4 shadowProjPos = mul(shadowViewProj, float4(worldPos, 1));" << std::endl;
118 ss << " shadowProjPos /= shadowProjPos.w;" << std::endl;
119 ss << " float2 shadowSampleTexCoord = shadowProjPos.xy;" << std::endl;
120 ss << " float shadowDepth = tex2D(shadowMap, shadowSampleTexCoord).r;" << std::endl;
121 ss << " float shadowDistance = shadowDepth * shadowFarClip;" << std::endl;
122 ss << " clip(shadowDistance - distanceFromLight + 0.1);" << std::endl;
123 ss << "}" << std::endl;
124 }
125
126 ss << "float4 SO3_DeferredLightDirectional_ps(float2 texCoord : TEXCOORD0," << std::endl;
127 ss << " float3 ray : TEXCOORD1," << std::endl;
128 ss << " " << gbuffer->GetGBufferCompositorPixelInputStructureTypeName() << " gBuffer," << std::endl; // Input parameters (list of mrts)
129 ss << " uniform float3 lightDir," << std::endl;
130 ss << " uniform float farClipDistance," << std::endl;
131
132 // Shadow parameters
134 {
135 ss << " uniform float4x4 invView," << std::endl;
136 ss << " uniform float4x4 shadowViewProjMat," << std::endl;
137 ss << " uniform sampler2D ShadowTex : register(s" << gbuffer->GetNumberMrt() << ")," << std::endl;
138 ss << " uniform float3 shadowCamPos," << std::endl;
139 ss << " uniform float shadowFarClip," << std::endl;
140 }
141
142 // Attributes of light
143 ss << " uniform float4 lightDiffuseColor," << std::endl;
144 ss << " uniform float4 lightSpecularColor," << std::endl;
145 ss << " uniform float lightPower" << std::endl;
146 ss << " ) : COLOR " << std::endl;
147 ss << "{" << std::endl;
148
149 // Attributes
150 ss << " float3 colour = gBuffer.GetDiffuse(texCoord);" << std::endl;
151 ss << " float specularity = gBuffer.GetShininess(texCoord);" << std::endl;
152 ss << " float distance = gBuffer.GetDepth(texCoord);" << std::endl;
153 ss << " float3 normal = gBuffer.GetNormal(texCoord);" << std::endl;
154
155 // Calculate position of texel in view space
156 ss << " float3 viewPos = normalize(ray)*distance*(farClipDistance - 0.01);" << std::endl;
157
158 // Calculate light direction and distance
159 ss << " float3 objToLightDir = -lightDir.xyz;" << std::endl;
160
161 // Check in/out shadows
163 ss << " checkShadow(ShadowTex, viewPos, invView, shadowViewProjMat, shadowFarClip, shadowCamPos);" << std::endl;
164
165 // Calculate diffuse colour
166 ss << " float3 total_light_contrib;" << std::endl;
167 ss << " total_light_contrib = max(0.0,dot(objToLightDir, normal)) * lightDiffuseColor.rgb;" << std::endl;
168
169 // Calculate specular component
170 ss << " float3 viewDir = -normalize(viewPos);" << std::endl;
171 ss << " float3 h = normalize(viewDir + objToLightDir);" << std::endl;
172 ss << " float3 light_specular = pow(max(dot(normal, h), 0), specularity) * lightSpecularColor.rgb;" << std::endl;
173
174 // If GBuffer supports specular color, compute specular component using the material specular colour too.
176 ss << " light_specular *= gBuffer.GetSpecular(texCoord);" << std::endl;
177
178 // Add specular colour to total light contribution
179 ss << " total_light_contrib += light_specular;" << std::endl;
180 ss << " total_light_contrib *= lightPower;" << std::endl;
181 ss << " return float4(total_light_contrib*colour, 0.0);" << std::endl;
182 ss << "}" << std::endl;
183
184 // Prepare shader generation
185 Ogre::String programSource = ss.str();
186 Ogre::String programName = materialBaseName +"Shaders/Pixel/"+ gbuffer->GetName() + Ogre::StringConverter::toString(permutationValue);
187
188#if SO3_DEBUG
189 // Show the generated vertex program in the log.
190 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(programSource, Ogre::LML_CRITICAL);
191#endif
192
193 // Create shader object
194 // TODO in another group than Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME?
195 Ogre::HighLevelGpuProgramPtr ptrProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(programName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", Ogre::GPT_FRAGMENT_PROGRAM);
196 ptrProgram->setSource(programSource);
197 ptrProgram->setParameter("entry_point", "SO3_DeferredLightDirectional_ps");
198 ptrProgram->setParameter("profiles", "ps_4_0 ps_2_x arbfp1");
199
200 // Bind our function parameters to Ogre's related values.
201 const Ogre::GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters();
202 if (params->_findNamedConstantDefinition("lightDiffuseColor"))
203 params->setNamedAutoConstant("lightDiffuseColor", Ogre::GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, 0);
204 if (params->_findNamedConstantDefinition("lightSpecularColor"))
205 params->setNamedAutoConstant("lightSpecularColor", Ogre::GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0);
206 if (params->_findNamedConstantDefinition("lightPower"))
207 params->setNamedAutoConstant("lightPower", Ogre::GpuProgramParameters::ACT_LIGHT_POWER_SCALE, 0);
208 if (params->_findNamedConstantDefinition("lightDir"))
209 params->setNamedAutoConstant("lightDir", Ogre::GpuProgramParameters::ACT_LIGHT_DIRECTION_VIEW_SPACE, 0);
210 if (params->_findNamedConstantDefinition("farClipDistance"))
211 params->setNamedAutoConstant("farClipDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
212
213 // Shadows autoparams
214 if ((permutationValue & SDeferredLightPermutation::SO3_LP_CAST_SHADOWS) && (params->_findNamedConstantDefinition("invView")))
215 params->setNamedAutoConstant("invView", Ogre::GpuProgramParameters::ACT_INVERSE_VIEW_MATRIX);
216
217 // Return compositor pixel shader
218 ptrProgram->load();
219 return Ogre::GpuProgramPtr(ptrProgram);
220}
221
222Ogre::MaterialPtr SDeferredLightDirectionalMaterialGenerator::GenerateTemplateMaterial(SGBuffer* gbuffer, Ogre::uint32 permutationValue)
223{
224 Ogre::MaterialPtr matPtr = SDeferredLightMaterialGenerator::GenerateTemplateMaterial(gbuffer, permutationValue);
225 Ogre::Pass* ogrePass = matPtr->getTechnique(0)->getPass(0);
226 ogrePass->setDepthCheckEnabled(false);
227 ogrePass->setSceneBlending(Ogre::SBT_ADD);
228 return matPtr;
229}
230
231}
std::string GetName() const
virtual Ogre::GpuProgramPtr GenerateFragmentShader(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::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.