1 /*
2  Copyright (c) 2013 yvt
3 
4  This file is part of OpenSpades.
5 
6  OpenSpades is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OpenSpades is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OpenSpades.  If not, see <http://www.gnu.org/licenses/>.
18 
19  */
20 
21 #include "GLDynamicLightShader.h"
22 #include <Core/Settings.h>
23 #include "GLImage.h"
24 #include "GLProgramManager.h"
25 #include "GLRenderer.h"
26 
27 namespace spades {
28 	namespace draw {
GLDynamicLightShader()29 		GLDynamicLightShader::GLDynamicLightShader()
30 		    : dynamicLightOrigin("dynamicLightOrigin"),
31 		      dynamicLightColor("dynamicLightColor"),
32 		      dynamicLightRadius("dynamicLightRadius"),
33 		      dynamicLightRadiusInversed("dynamicLightRadiusInversed"),
34 		      dynamicLightSpotMatrix("dynamicLightSpotMatrix"),
35 		      dynamicLightProjectionTexture("dynamicLightProjectionTexture")
36 
37 		{
38 			lastRenderer = NULL;
39 		}
40 
41 		std::vector<GLShader *>
RegisterShader(spades::draw::GLProgramManager * r)42 		GLDynamicLightShader::RegisterShader(spades::draw::GLProgramManager *r) {
43 			std::vector<GLShader *> shaders;
44 
45 			shaders.push_back(r->RegisterShader("Shaders/DynamicLight/Common.fs"));
46 			shaders.push_back(r->RegisterShader("Shaders/DynamicLight/Common.vs"));
47 
48 			shaders.push_back(r->RegisterShader("Shaders/DynamicLight/MapNull.fs"));
49 			shaders.push_back(r->RegisterShader("Shaders/DynamicLight/MapNull.vs"));
50 
51 			return shaders;
52 		}
53 
operator ()(GLRenderer * renderer,spades::draw::GLProgram * program,const GLDynamicLight & light,int texStage)54 		int GLDynamicLightShader::operator()(GLRenderer *renderer, spades::draw::GLProgram *program,
55 		                                     const GLDynamicLight &light, int texStage) {
56 			if (lastRenderer != renderer) {
57 				whiteImage = static_cast<GLImage *>(renderer->RegisterImage("Gfx/White.tga"));
58 				lastRenderer = renderer;
59 			}
60 
61 			const client::DynamicLightParam &param = light.GetParam();
62 
63 			IGLDevice *device = renderer->GetGLDevice();
64 			dynamicLightOrigin(program);
65 			dynamicLightColor(program);
66 			dynamicLightRadius(program);
67 			dynamicLightRadiusInversed(program);
68 			dynamicLightSpotMatrix(program);
69 			dynamicLightProjectionTexture(program);
70 
71 			dynamicLightOrigin.SetValue(param.origin.x, param.origin.y, param.origin.z);
72 			dynamicLightColor.SetValue(param.color.x, param.color.y, param.color.z);
73 			dynamicLightRadius.SetValue(param.radius);
74 			dynamicLightRadiusInversed.SetValue(1.f / param.radius);
75 
76 			if (param.type == client::DynamicLightTypeSpotlight) {
77 				device->ActiveTexture(texStage);
78 				static_cast<GLImage *>(param.image)->Bind(IGLDevice::Texture2D);
79 				dynamicLightProjectionTexture.SetValue(texStage);
80 				texStage++;
81 
82 				dynamicLightSpotMatrix.SetValue(light.GetProjectionMatrix());
83 
84 				// bad hack to make texture clamped to edge
85 				device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS,
86 				                     IGLDevice::ClampToEdge);
87 				device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT,
88 				                     IGLDevice::ClampToEdge);
89 
90 			} else {
91 				device->ActiveTexture(texStage);
92 				whiteImage->Bind(IGLDevice::Texture2D);
93 				dynamicLightProjectionTexture.SetValue(texStage);
94 				texStage++;
95 
96 				dynamicLightSpotMatrix.SetValue(Matrix4::Identity());
97 			}
98 
99 			device->ActiveTexture(texStage);
100 
101 			return texStage;
102 		}
103 
Cull(const GLDynamicLight & light,const spades::AABB3 & box)104 		bool GLDynamicLightShader::Cull(const GLDynamicLight &light, const spades::AABB3 &box) {
105 			// TOOD: more tighter check?
106 			// TODO: spotlight check?
107 			// TODO: move this function to GLDynamicLight?
108 			const client::DynamicLightParam &param = light.GetParam();
109 			return box.Inflate(param.radius) && param.origin;
110 		}
111 
SphereCull(const GLDynamicLight & light,const spades::Vector3 & center,float radius)112 		bool GLDynamicLightShader::SphereCull(const GLDynamicLight &light,
113 		                                      const spades::Vector3 &center, float radius) {
114 			const client::DynamicLightParam &param = light.GetParam();
115 			float maxDistance = radius + param.radius;
116 			return (center - param.origin).GetPoweredLength() < maxDistance * maxDistance;
117 		}
118 	}
119 }
120