Merged 15170:15635 from trunk (no conflicts or even merges)
[blender.git] / source / gameengine / Ketsji / BL_BlenderShader.cpp
1
2 #include "DNA_customdata_types.h"
3 #include "DNA_material_types.h"
4
5 #include "BL_BlenderShader.h"
6 #include "BL_Material.h"
7
8 #ifdef BLENDER_GLSL
9 #include "GPU_extensions.h"
10 #include "GPU_material.h"
11 #endif
12
13 #include "RAS_MeshObject.h"
14 #include "RAS_IRasterizer.h"
15
16 const bool BL_BlenderShader::Ok()const
17 {
18 #ifdef BLENDER_GLSL
19         return (mGPUMat != 0);
20 #else
21         return 0;
22 #endif
23 }
24
25 BL_BlenderShader::BL_BlenderShader(struct Material *ma, int lightlayer)
26 :
27 #ifdef BLENDER_GLSL
28         mGPUMat(0),
29 #endif
30         mBound(false),
31         mLightLayer(lightlayer)
32 {
33 #ifdef BLENDER_GLSL
34         if(ma) {
35                 GPU_material_from_blender(ma);
36                 mGPUMat = ma->gpumaterial;
37         }
38 #endif
39 }
40
41 BL_BlenderShader::~BL_BlenderShader()
42 {
43 #ifdef BLENDER_GLSL
44         if(mGPUMat) {
45                 GPU_material_unbind(mGPUMat);
46                 mGPUMat = 0;
47         }
48 #endif
49 }
50
51 void BL_BlenderShader::SetProg(bool enable)
52 {
53 #ifdef BLENDER_GLSL
54         if(mGPUMat) {
55                 if(enable) {
56                         GPU_material_bind(mGPUMat, mLightLayer);
57                         mBound = true;
58                 }
59                 else {
60                         GPU_material_unbind(mGPUMat);
61                         mBound = false;
62                 }
63         }
64 #endif
65 }
66
67 int BL_BlenderShader::GetAttribNum()
68 {
69 #ifdef BLENDER_GLSL
70         GPUVertexAttribs attribs;
71         int i, enabled = 0;
72
73         if(!mGPUMat)
74                 return enabled;
75
76         GPU_material_vertex_attributes(mGPUMat, &attribs);
77
78     for(i = 0; i < attribs.totlayer; i++)
79                 if(attribs.layer[i].glindex+1 > enabled)
80                         enabled= attribs.layer[i].glindex+1;
81         
82         if(enabled > BL_MAX_ATTRIB)
83                 enabled = BL_MAX_ATTRIB;
84
85         return enabled;
86 #else
87         return 0;
88 #endif
89 }
90
91 void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat)
92 {
93 #ifdef BLENDER_GLSL
94         GPUVertexAttribs attribs;
95         int i, attrib_num;
96
97         ras->SetAttribNum(0);
98
99         if(!mGPUMat)
100                 return;
101
102         if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
103                 GPU_material_vertex_attributes(mGPUMat, &attribs);
104                 attrib_num = GetAttribNum();
105
106                 ras->SetTexCoordNum(0);
107                 ras->SetAttribNum(attrib_num);
108                 for(i=0; i<attrib_num; i++)
109                         ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, i);
110
111                 for(i = 0; i < attribs.totlayer; i++) {
112                         if(attribs.layer[i].glindex > attrib_num)
113                                 continue;
114
115                         if(attribs.layer[i].type == CD_MTFACE) {
116                                 if(!mat->uvName.IsEmpty() && strcmp(mat->uvName.ReadPtr(), attribs.layer[i].name) == 0)
117                                         ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex);
118                                 else if(!mat->uv2Name.IsEmpty() && strcmp(mat->uv2Name.ReadPtr(), attribs.layer[i].name) == 0)
119                                         ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV2, attribs.layer[i].glindex);
120                                 else
121                                         ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex);
122                         }
123                         else if(attribs.layer[i].type == CD_TANGENT)
124                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, attribs.layer[i].glindex);
125                         else if(attribs.layer[i].type == CD_ORCO)
126                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_ORCO, attribs.layer[i].glindex);
127                         else if(attribs.layer[i].type == CD_NORMAL)
128                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_NORM, attribs.layer[i].glindex);
129                         else if(attribs.layer[i].type == CD_MCOL)
130                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_VCOL, attribs.layer[i].glindex);
131                         else
132                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, attribs.layer[i].glindex);
133                 }
134
135                 ras->EnableTextures(true);
136         }
137         else
138                 ras->EnableTextures(false);
139 #endif
140 }
141
142 void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty )
143 {
144 #ifdef BLENDER_GLSL
145         float obmat[4][4], viewmat[4][4], viewinvmat[4][4];
146
147         if(!mGPUMat || !mBound)
148                 return;
149
150         MT_Matrix4x4 model;
151         model.setValue(ms.m_OpenGLMatrix);
152         MT_Matrix4x4 view;
153         rasty->GetViewMatrix(view);
154
155         model.getValue((float*)obmat);
156         view.getValue((float*)viewmat);
157
158         view.invert();
159         view.getValue((float*)viewinvmat);
160
161         GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat);
162 #endif
163 }
164
165 bool BL_BlenderShader::Equals(BL_BlenderShader *blshader)
166 {
167 #ifdef BLENDER_GLSL
168         /* to avoid unneeded state switches */
169         return (blshader && mGPUMat == blshader->mGPUMat && mLightLayer == blshader->mLightLayer);
170 #else
171         return true;
172 #endif
173 }
174
175 // eof