Merging r50625 through r51896 from trunk into soc-2011-tomato
[blender.git] / source / gameengine / Ketsji / BL_BlenderShader.cpp
1 /** \file gameengine/Ketsji/BL_BlenderShader.cpp
2  *  \ingroup ketsji
3  */
4
5 #include "DNA_customdata_types.h"
6 #include "DNA_material_types.h"
7 #include "DNA_scene_types.h"
8
9 #include "BLI_utildefines.h"
10
11 #include "BKE_global.h"
12 #include "BKE_main.h"
13 #include "BKE_DerivedMesh.h"
14
15 #include "BL_BlenderShader.h"
16 #include "BL_Material.h"
17
18 #include "GPU_extensions.h"
19 #include "GPU_material.h"
20
21 #include "RAS_BucketManager.h"
22 #include "RAS_MeshObject.h"
23 #include "RAS_IRasterizer.h"
24  
25 BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer)
26 :
27         mScene(scene),
28         mMat(ma),
29         mLightLayer(lightlayer),
30         mGPUMat(NULL)
31 {
32         mBlenderScene = scene->GetBlenderScene();
33         mAlphaBlend = GPU_BLEND_SOLID;
34
35         ReloadMaterial();
36 }
37
38 BL_BlenderShader::~BL_BlenderShader()
39 {
40         if (mGPUMat)
41                 GPU_material_unbind(mGPUMat);
42 }
43
44 void BL_BlenderShader::ReloadMaterial()
45 {
46         mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat) : NULL;
47 }
48
49 void BL_BlenderShader::SetProg(bool enable, double time)
50 {
51         if (VerifyShader()) {
52                 if (enable)
53                         GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1);
54                 else
55                         GPU_material_unbind(mGPUMat);
56         }
57 }
58
59 int BL_BlenderShader::GetAttribNum()
60 {
61         GPUVertexAttribs attribs;
62         int i, enabled = 0;
63
64         if (!VerifyShader())
65                 return enabled;
66
67         GPU_material_vertex_attributes(mGPUMat, &attribs);
68
69         for (i = 0; i < attribs.totlayer; i++)
70                 if (attribs.layer[i].glindex+1 > enabled)
71                         enabled= attribs.layer[i].glindex+1;
72         
73         if (enabled > BL_MAX_ATTRIB)
74                 enabled = BL_MAX_ATTRIB;
75
76         return enabled;
77 }
78
79 void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat)
80 {
81         GPUVertexAttribs attribs;
82         GPUMaterial *gpumat;
83         int i, attrib_num;
84
85         ras->SetAttribNum(0);
86
87         if (!VerifyShader())
88                 return;
89         
90         gpumat = mGPUMat;
91
92         if (ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
93                 GPU_material_vertex_attributes(gpumat, &attribs);
94                 attrib_num = GetAttribNum();
95
96                 ras->SetTexCoordNum(0);
97                 ras->SetAttribNum(attrib_num);
98                 for (i=0; i<attrib_num; i++)
99                         ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, i);
100
101                 for (i = 0; i < attribs.totlayer; i++) {
102                         if (attribs.layer[i].glindex > attrib_num)
103                                 continue;
104
105                         if (attribs.layer[i].type == CD_MTFACE) {
106                                 if (!mat->uvName.IsEmpty() && strcmp(mat->uvName.ReadPtr(), attribs.layer[i].name) == 0)
107                                         ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex);
108                                 else if (!mat->uv2Name.IsEmpty() && strcmp(mat->uv2Name.ReadPtr(), attribs.layer[i].name) == 0)
109                                         ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV2, attribs.layer[i].glindex);
110                                 else
111                                         ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex);
112                         }
113                         else if (attribs.layer[i].type == CD_TANGENT)
114                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, attribs.layer[i].glindex);
115                         else if (attribs.layer[i].type == CD_ORCO)
116                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_ORCO, attribs.layer[i].glindex);
117                         else if (attribs.layer[i].type == CD_NORMAL)
118                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_NORM, attribs.layer[i].glindex);
119                         else if (attribs.layer[i].type == CD_MCOL)
120                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_VCOL, attribs.layer[i].glindex);
121                         else
122                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, attribs.layer[i].glindex);
123                 }
124         }
125 }
126
127 void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
128 {
129         float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4];
130         GPUMaterial *gpumat;
131
132         gpumat = mGPUMat;
133
134         if (!gpumat || !GPU_material_bound(gpumat))
135                 return;
136
137         MT_Matrix4x4 model;
138         model.setValue(ms.m_OpenGLMatrix);
139         const MT_Matrix4x4& view = rasty->GetViewMatrix();
140         const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix();
141
142         // note: getValue gives back column major as needed by OpenGL
143         model.getValue((float*)obmat);
144         view.getValue((float*)viewmat);
145         viewinv.getValue((float*)viewinvmat);
146
147         if (ms.m_bObjectColor)
148                 ms.m_RGBAcolor.getValue((float *)obcol);
149         else
150                 obcol[0] = obcol[1] = obcol[2] = obcol[3] = 1.0f;
151
152         float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f;
153         GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol, auto_bump_scale);
154
155         mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol);
156 }
157
158 int BL_BlenderShader::GetAlphaBlend()
159 {
160         return mAlphaBlend;
161 }
162
163 bool BL_BlenderShader::Equals(BL_BlenderShader *blshader)
164 {
165         /* to avoid unneeded state switches */
166         return (blshader && mMat == blshader->mMat && mLightLayer == blshader->mLightLayer);
167 }
168
169 // eof