# need help with using multi-texture in pfx

**URL:** <https://forums.imgtec.com/t/need-help-with-using-multi-texture-in-pfx/2237>\
**Category:** PowerVR Insider\
**Tags:** pvrshaman, pvrshadereditor\
**Created:** [January 23, 2015, 12:30am UTC](https://forums.imgtec.com/t/need-help-with-using-multi-texture-in-pfx/2237 "2015-01-23T00:30:00Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![blamejane](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.imgtec.com/blamejane/32/93_2.png) [@blamejane](https://forums.imgtec.com/u/blamejane)\
**Post date:** [January 23, 2015, 12:30am UTC](https://forums.imgtec.com/t/need-help-with-using-multi-texture-in-pfx/2237/1 "2015-01-23T00:30:00Z")

</div>

I’m using a POD file with shaders in a PFX file. I’ve got a model of a car, which I have a base texture applied. I am trying to apply some decals to the car, by blending another texture onto the base. I’m seriously having problems though as I can’t figure out how exactly to do this. I know it’s possible as the Alpha Blend example uses transparency in the 1st quad. The problem is, I can’t figure out how to accomplish the same technique using shaders that are defined in the pfx.  
  
  
  
Here’s how my render mesh and draw mesh are defined:  
  
  
  
``

- (void) renderMeshes:(SPODNode _)pNode withIndex:(int)index andEffect:(GLuint)uiFXID_  
  
_{_  
  
   
  
   
  
_// Gets the node model matrix_  
  
_PVRTMat4 mWorld;_  
  
_PVRTMat4 mWorldView;_  
  
   
  
_mWorld = \_broncoScene.GetWorldMatrix(pNode);_  
  
   
  
_mWorld = [self sizeTiresAndWheels:index axis:mWorld node:pNode withIndex:index];_  
  
   
  
_mWorld = [self applySuspensionLift:index axis:mWorld];_  
  
   
  
_SPODMaterial pMaterial = &\_broncoScene.pMaterial[pNode-\>nIdxMaterial];_  
  
   
  
_mWorldView = \_viewMatrix \* \_rotationX \* mWorld;_  
  
   
  
   
  
_// Set the blend mode_  
  
_// Based in the info stored in the material by PVRShaman._  
  
_// We check whether the blend mode is ‘opaque’ (ONE,ZERO)._  
  
_// Otherwise we enable blending and set the corresponding operations._  
  
_if (\_broncoScene.pMaterial[pNode-\>nIdxMaterial].eBlendSrcRGB == ePODBlendFunc\_ONE && \_broncoScene.pMaterial[pNode-\>nIdxMaterial].eBlendDstRGB == ePODBlendFunc\_ZERO)_  
  
_{_  
  
_glDisable(GL\_BLEND);_  
  
_}_  
  
_else_  
  
_{_  
  
_glEnable(GL\_BLEND);_  
  
_// glBlendFunc(GL\_SRC\_ALPHA, GL\_ONE\_MINUS\_SRC\_ALPHA);_  
  
_glBlendFunc(\_broncoScene.pMaterial[pNode-\>nIdxMaterial].eBlendSrcRGB, \_broncoScene.pMaterial[pNode-\>nIdxMaterial].eBlendDstRGB);_  
  
_}_  
  
   
  
   
  
   
  
_// Now process PVRShaman semantics and set-up the associated uniforms._  
  
_const CPVRTArray& aUniforms = \_pFX[uiFXID]-\>GetUniformArray();_  
  
_for(unsigned int j = 0; j \< aUniforms.GetSize(); ++j)_  
  
_{_  
  
_switch(aUniforms[j].nSemantic)_  
  
_{_  
  
_case ePVRTPFX\_UsWORLDVIEWPROJECTION:_  
  
_{_  
  
_PVRTMat4 mWVP;_  
  
   
  
_// Passes the world-view-projection matrix (WVP) to the shader to transform the vertices_  
  
_mWVP = \_projectionMatrix \* mWorldView;_  
  
_glUniformMatrix4fv(aUniforms[j].nLocation, 1, GL\_FALSE, mWVP.f);_  
  
_}_  
  
_break;_  
  
_case ePVRTPFX\_UsWORLDVIEWIT:_  
  
_{_  
  
_PVRTMat4 mWorldViewI, mWorldViewIT;_  
  
   
  
_// Passes the inverse transpose of the world-view matrix to the shader to transform the normals_  
  
_mWorldViewI = mWorldView.inverse();_  
  
_mWorldViewIT = mWorldViewI.transpose();_  
  
   
  
_PVRTMat3 WorldViewIT = PVRTMat3(mWorldViewIT);_  
  
   
  
_glUniformMatrix3fv(aUniforms[j].nLocation, 1, GL\_FALSE, WorldViewIT.f);_  
  
_}_  
  
_break;_  
  
_case ePVRTPFX\_UsWORLDVIEW:_  
  
_{_  
  
_glUniformMatrix4fv(aUniforms[j].nLocation, 1, GL\_FALSE, \_viewMatrix.f);_  
  
_}_  
  
_break;_  
  
_case ePVRTPFX\_UsVIEWIT:_  
  
_{_  
  
_PVRTMat4 mViewI, mViewIT;_  
  
   
  
_/_ Passes the inverse transpose of the model-view matrix to the shader to transform the normals \*/  
  
mViewI = \_viewMatrix.inverse();  
  
mViewIT= mViewI.transpose();  
  
  
  
PVRTMat3 ViewIT = PVRTMat3(mViewIT);  
  
  
  
glUniformMatrix3fv(aUniforms[j].nLocation, 1, GL\_FALSE, ViewIT.f);  
  
}  
  
break;  
  
case ePVRTPFX\_UsLIGHTDIREYE:  
  
{  
  
  
  
  
  
//

* * *
test...  
  
  
//
* * *
  
  
// Reads the light direction from the scene.  
PVRTVec4 vLightDirection;  
PVRTVec3 vPos;  
// vLightDirection = \_broncoScene.GetLightDirection(0);  
vLightDirection = PVRTVec4(0, 0, 0, 0);  
  
vLightDirection.x = -vLightDirection.x;  
vLightDirection.y = -vLightDirection.y;  
vLightDirection.z = -vLightDirection.z;  
  
  
  
/\*  
Sets the w component to 0, so when passing it to glLight(), it is  
considered as a directional light (as opposed to a spot light).  
\*/  
vLightDirection.w = 0;  
  
// Passes the light direction in eye space to the shader  
PVRTVec4 vLightDirectionEyeSpace;  
vLightDirectionEyeSpace = \_viewMatrix \* vLightDirection;  
  
glUniform3f(aUniforms[j].nLocation, vLightDirectionEyeSpace.x, vLightDirectionEyeSpace.y, vLightDirectionEyeSpace.z);  
}  
break;  
case eCUSTOMSEMANTIC\_DIFFUSECOLOUR:  
{  
glUniform4f(aUniforms[j].nLocation, pMaterial-\>pfMatDiffuse[0], pMaterial-\>pfMatDiffuse[1], pMaterial-\>pfMatDiffuse[2], 1.0f);  
}  
break;  
  
}  
}  
  
//set animation  
  
const CGFloat\* components = CGColorGetComponents([self bodyColor].CGColor);  
  
glUniform4f(glGetUniformLocation(\_pFX[uiFXID]-\>GetProgramHandle(), "diffuseColor"),components[0], components[1], components[2], 1);  
  
/\*  
Now that the model-view matrix is set and the materials ready,  
call another function to actually draw the mesh.  
\*/  
[self drawMesh:index withEffect: \_pFX[uiFXID]];  
glBindBuffer(GL\_ARRAY\_BUFFER, 0);  
  
  
  
}  
  
  
- (void)drawMesh:(int)i32NodeIndex withEffect:(CPVRTPFXEffect \*)pCurrentFX  
{  
// Get the mesh data from the POD file  
int i32MeshIndex = \_broncoScene.pNode[i32NodeIndex].nIdx;  
SPODMesh\* pMesh = &\_broncoScene.pMesh[i32MeshIndex];  
  
// bind the VBO for the mesh  
glBindBuffer(GL\_ARRAY\_BUFFER, \_puiVbo[i32MeshIndex]);  
  
// bind the index buffer, won't hurt if the handle is 0  
glBindBuffer(GL\_ELEMENT\_ARRAY\_BUFFER, \_puiIndexVbo[i32MeshIndex]);  
  
const CPVRTArray& Uniforms = pCurrentFX-\>GetUniformArray();  
  
// Set attributes and texture stages  
// The vertex data is already loaded into an VBO as 'interleaved data' (e.g. x,y,z,nx,ny,nz,u0,v0,...).  
// When using 'interleaved data' the last parameter in glVertexAttribPointer is just a numerical offset (in bytes) into the stream (e.g. 0, 12, 24).  
// Our tools use pMesh-\>sVertex.pData, etc. to store this offset only when using interleaved data.  
// If you do not want to use interleaved data you will need to create separated VBO from pMesh-\>sVertex.pData, pMesh-\>sNormals.pData, etc.  
// and set the offset (last parameter) to 0  
for(unsigned int j = 0; j \< Uniforms.GetSize(); ++j)  
{  
switch(Uniforms[j].nSemantic)  
{  
case ePVRTPFX\_UsPOSITION:  
{  
glVertexAttribPointer(Uniforms[j].nLocation, 3, GL\_FLOAT, GL\_FALSE, pMesh-\>sVertex.nStride, pMesh-\>sVertex.pData);  
glEnableVertexAttribArray(Uniforms[j].nLocation);  
}  
break;  
case ePVRTPFX\_UsNORMAL:  
{  
glVertexAttribPointer(Uniforms[j].nLocation, 3, GL\_FLOAT, GL\_FALSE, pMesh-\>sNormals.nStride, pMesh-\>sNormals.pData);  
glEnableVertexAttribArray(Uniforms[j].nLocation);  
}  
break;  
case ePVRTPFX\_UsUV:  
{  
glVertexAttribPointer(Uniforms[j].nLocation, 2, GL\_FLOAT, GL\_FALSE, pMesh-\>psUVW[0].nStride, pMesh-\>psUVW[0].pData);  
glEnableVertexAttribArray(Uniforms[j].nLocation);  
}  
break;  
  
case ePVRTPFX\_UsTEXTURE:  
{  
// Set the sampler variable to the texture unit/stage 0,1,2,etc.  
glUniform1i(Uniforms[j].nLocation, Uniforms[j].nIdx);  
}  
break;  
case eCUSTOMSEMANTIC\_TANGENT:  
{  
glVertexAttribPointer(Uniforms[j].nLocation, 3, GL\_FLOAT, GL\_FALSE, pMesh-\>sTangents.nStride, pMesh-\>sTangents.pData);  
  
}  
break;  
  
}  
}  
  
// Indexed Triangle list  
// Note: if you export you model and want to use this code, please export it as 'interleaved' triangle list.  
glDrawElements(GL\_TRIANGLES, pMesh-\>nNumFaces\*3, GL\_UNSIGNED\_SHORT, 0);  
  
// Safely disable the vertex attribute arrays  
for(unsigned int j = 0; j \< Uniforms.GetSize(); ++j)  
{  
switch(Uniforms[j].nSemantic)  
{  
case ePVRTPFX\_UsPOSITION:  
{  
glDisableVertexAttribArray(Uniforms[j].nLocation);  
}  
break;  
case ePVRTPFX\_UsNORMAL:  
{  
glDisableVertexAttribArray(Uniforms[j].nLocation);  
}  
break;  
case ePVRTPFX\_UsUV:  
{  
glDisableVertexAttribArray(Uniforms[j].nLocation);  
}  
break;  
}  
}  
  
// Un-bind our vertex and index buffers.  
glBindBuffer(GL\_ARRAY\_BUFFER, 0);  
glBindBuffer(GL\_ELEMENT\_ARRAY\_BUFFER, 0);  
  
}

---

<div class="post-metadata">

**Author:** ![PaulLy](https://avatars.discourse-cdn.com/v4/letter/p/958977/32.png) [@PaulLy](https://forums.imgtec.com/u/PaulLy)\
**Post date:** [January 28, 2015, 1:51pm UTC](https://forums.imgtec.com/t/need-help-with-using-multi-texture-in-pfx/2237/2 "2015-01-28T13:51:44Z")

</div>

Hi,  
  
  
  
Could you post the fragment shader code you are currently using to attempt this effect?  
  
  
  
Thanks,  
  
Paul.

---

<div class="post-metadata">

**Author:** ![blamejane](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.imgtec.com/blamejane/32/93_2.png) [@blamejane](https://forums.imgtec.com/u/blamejane)\
**Post date:** [January 28, 2015, 1:54pm UTC](https://forums.imgtec.com/t/need-help-with-using-multi-texture-in-pfx/2237/3 "2015-01-28T13:54:23Z")

</div>

Thanks PaulL, that’s the thing though, I don’t have the shaders. I’m trying to get help with creating them.

---

<div class="post-metadata">

**Author:** ![PaulLy](https://avatars.discourse-cdn.com/v4/letter/p/958977/32.png) [@PaulLy](https://forums.imgtec.com/u/PaulLy)\
**Post date:** [January 29, 2015, 10:17am UTC](https://forums.imgtec.com/t/need-help-with-using-multi-texture-in-pfx/2237/4 "2015-01-29T10:17:06Z")

</div>

You can use the PVRShaderEditor tool in the PowerVR SDK to view the .pfx file.  
  
  
  
[https://www.imgcommunity.local/developers/powervr/tools/pvrshadereditor/](https://www.imgcommunity.local/developers/powervr/tools/pvrshadereditor/)

---

<div class="post-metadata">

**Author:** ![PaulLy](https://avatars.discourse-cdn.com/v4/letter/p/958977/32.png) [@PaulLy](https://forums.imgtec.com/u/PaulLy)\
**Post date:** [February 6, 2015, 11:01am UTC](https://forums.imgtec.com/t/need-help-with-using-multi-texture-in-pfx/2237/5 "2015-02-06T11:01:28Z")

</div>

You achieve the effect by creating a POD for the car model, which should have a base texture, and a decal texture. You can then use a fragment shader defined in the PFX which takes two texture uniforms. The first texture handle would reference the car base texture, and the second handle should reference the decal you wish to use. The shader can then blend between the two textures on to the model.  
  
  
  
By changing the texture referenced by the shader handle, you can then apply different decals to several cars in a scene.

---

<div class="post-metadata">

**Author:** ![blamejane](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.imgtec.com/blamejane/32/93_2.png) [@blamejane](https://forums.imgtec.com/u/blamejane)\
**Post date:** [February 6, 2015, 1:44pm UTC](https://forums.imgtec.com/t/need-help-with-using-multi-texture-in-pfx/2237/6 "2015-02-06T13:44:18Z")

</div>

Thanks Pauil,  
  
  
  
Here’s [how the effect looks](https://www.youtube.com/watch?v=i-h0iThd_BY)applied.  
  
  
  
Not sure how to modify this further, but here’s my effect code:  
  
  
  
`
[TEXTURE]
NAME cubemap
PATH bronco_cubemap_rotated2.pvr
MINIFICATION LINEAR
MAGNIFICATION	LINEAR
MIPMAP LINEAR
WRAP_S CLAMP
WRAP_T CLAMP
[/TEXTURE]

[TEXTURE]
NAME bodyBase
PATH broncoBody0017_texture.pvr
MINIFICATION	LINEAR
MAGNIFICATION	LINEAR
MIPMAP LINEAR
WRAP_S REPEAT
WRAP_T REPEAT

[/TEXTURE]
// ENVIRONMENT CUBEMAP /////////////////////////////////////////////////////////////////////
//
// Effect 3 from skybox2 example. Displays a textured bronco with diffuse lighting and a
// second texture cube map of a garage, which is applied using a reflection vector as texture coordinates.
// This makes it look like the bronco is reflecting the garage.
//

[VERTEXSHADER]
NAME envMapVertShader

[GLSL_CODE]
attribute vec3	myVertex;
attribute vec3	myNormal;
attribute vec2	myUV;

uniform mat4	myMVPMatrix;
uniform mat3	myModelViewIT;
uniform mat4	myModelView;
uniform mediump vec3 EyePosModel;

uniform mediump vec3	myLightDirection;
varying highp	float	fDiffuse;
varying lowp	vec2	fTexCoord;

uniform mediump float myFrame;
uniform mediump float fAnim;
varying lowp vec3 fReflectVec;

uniform vec4 diffuseColor;
varying vec4 baseColor;

void main(void)
{
mediump vec4 myVertex4 = vec4(myVertex, 1);

gl_Position = myMVPMatrix * myVertex4;
mediump vec3 fTransNormal = myModelViewIT * myNormal;

fDiffuse = (0.05 * dot(fTransNormal, myLightDirection) + 0.95) * 0.5;

mediump vec3 EyeDir = vec3(0.0,-1.0,0.0) - vec3(myModelView * myVertex4);
fReflectVec = myModelViewIT * reflect(EyeDir, normalize(fTransNormal) );

baseColor = diffuseColor;

fTexCoord	= myUV.st;
}
[/GLSL_CODE]
[/VERTEXSHADER]

[FRAGMENTSHADER]
NAME envMapFragShader

[GLSL_CODE]
const mediump float MixRatio = 0.15;

varying lowp vec4 baseColor;
varying lowp vec2	fTexCoord;
varying lowp vec3 fReflectVec;

uniform sampler2D sampler2d;
uniform samplerCube myCubeMap;

void main (void)
{

// Draw the static base
mediump vec3 envColor = vec3 (texture2D(sampler2d, fTexCoord) * baseColor);

// Do a lookup into the environment map.
mediump vec3 envColor2 = vec3 (textureCube(myCubeMap, fReflectVec));

// Mix them
envColor = mix(envColor, envColor2, MixRatio);

gl_FragColor = vec4 (envColor, 1.0);

}

[/GLSL_CODE]
[/FRAGMENTSHADER]

[EFFECT]
NAME environmentMapEffect

// GLOBALS UNIFORMS
UNIFORM myModelViewIT WORLDVIEWIT
UNIFORM myMVPMatrix WORLDVIEWPROJECTION
UNIFORM myModelView WORLDVIEW
UNIFORM	myLightDirection	LIGHTDIREYE
UNIFORM	sampler2d TEXTURE0
UNIFORM	myCubeMap TEXTURE1

// ATTRIBUTES
ATTRIBUTE myVertex	POSITION
ATTRIBUTE	myNormal	NORMAL
ATTRIBUTE	myUV UV

VERTEXSHADER envMapVertShader
FRAGMENTSHADER envMapFragShader
TEXTURE 0 bodyBase
TEXTURE 1 cubemap
[/EFFECT]

`
