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