Implementing proper lighting in DX9 ($100-$150 REWARD to the person who helps me!)

Started by
18 comments, last by Tom_W 4 years, 4 months ago

I have never used any Quake related source code seriously myself, so can't help. Because you copied this partially from someone else, it's probably not that easy to figure out every things purpose.

Bezier::tessellate(int L) is surely unrelated. It looks like code for bezier patches, which are curved surfaces Quake III uses.

You need to follow how the data is loaded from file, maybe somehow converted, and finally ends up in your games draw calls. But it's mostly about ‘faces’ or ‘triangles’, less about vertices or planes i guess.

The easiest way would be to keep the original data. It's still useful e.g. for collision detection so you don't want to break anything here.

First look what a draw call is. Is it a single triangle, or all triangles of a convex cell? In any case, that's where you can get the data, subivide it and draw that instead. You can do this per frame at first to get going. Try to draw Points at vertices ("debug visualization"), and lines at edges, to verify visually. Then draw an extra vertex at the edges midpoints, add edges and so on. Then you can think of how to store the new data, do it just once at level load, how to link it to the original draw calls, etc.

If you don't have a way to draw such debug visualization yet, work on this first. Ability to draw points and lines from anywhere in the code gives you feedback on correctness of geometric assumptions, or lets you figure out what a certain piece of code is doing. It helps with any kind of doubts and uncertainty - very important for both learning and debugging.

Tip: Because it may conflict with render states, it works best to have buffers for points, lines, triangles. std::vector would be fine to get going.

Here is a piece of what i'm using. Ignore how messy this is, but you get the idea…

	void RenderPoint (float *v1, float *color)
	{
		if (numVertices[POINTS]+1 >= VERTEX_LIST_SIZE) return;	
			vertices[POINTS][numVertices[POINTS]++].Set (v1, color); 
	}

	void RenderLine (float *v1, float *v2, float *color)
	{
		if (numVertices[LINES]+2 >= VERTEX_LIST_SIZE*2) return;		
			vertices[LINES][numVertices[LINES]++].Set (v1, color); 
			vertices[LINES][numVertices[LINES]++].Set (v2, color); 
	}

	void RenderTriangle (float *v1, float *v2, float *v3, float *color)
	{
		if (numVertices[TRIANGLES]+3 >= VERTEX_LIST_SIZE*3) return;		
			vertices[TRIANGLES][numVertices[TRIANGLES]++].Set (v1, color); 
			vertices[TRIANGLES][numVertices[TRIANGLES]++].Set (v2, color); 
			vertices[TRIANGLES][numVertices[TRIANGLES]++].Set (v3, color); 
	}

And i have something with more comfort on top of that, which looks like this:

	inline void RenderLine (sVec3 pos1, sVec3 pos2, float r, float g, float b, float a=1.0)
	{
		float col[4] = {r,g,b,a};
		simpleVis.RenderLine (&pos1[0], &pos2[0], col);
	}
	inline void RenderVector (sVec3 pos, sVec3 vec, float r, float g, float b, float a=1.0)
	{
		RenderLine (pos, sVec3(pos + vec), r, g, b, a);
	}
	inline void RenderTriangle (sVec3 pos1, sVec3 pos2, sVec3 pos3, float r, float g, float b, float a=1.0)
	{
		float col[4] = {r,g,b,a};
		simpleVis.RenderTriangle (&pos1[0], &pos2[0], &pos3[0], col);
	}

… so i push such points from anywhere in the code, and render it after the frame is done on top, and resetting the buffers for the next frame. Very helpful.

Tom_W said:
Trying HLSL isn't getting me far(though I haven't really gotten that far into it yet. I've considered upgrading to DX11, but my thinking behind staying with DX9

Just stick at it. Shaders seem not important yet for you - it's more likely distracting. DX9 or 11… who cares, it's just output but not really the game.

Advertisement

It seems with fog and d3dlight, I can achieve the effects I want. If I want a flashlight effect, I can simply blanket the screen(HUD excluded) with an alpha texture, when the flashlight effect is on, make the fog more distant, reduce its density, and have the player only see through the transparent hole made to look like an effect made by a flashlight. No need for tesselation, no need for HLSL per pixel lighting, it should give the effect I desire. But if anyone could still educate me on HLSL/pixel lighting or come up with a tesselation function I'm all ears ?

JoeJ said:

I have never used any Quake related source code seriously myself, so can't help. Because you copied this partially from someone else, it's probably not that easy to figure out every things purpose.

Bezier::tessellate(int L) is surely unrelated. It looks like code for bezier patches, which are curved surfaces Quake III uses.

You need to follow how the data is loaded from file, maybe somehow converted, and finally ends up in your games draw calls. But it's mostly about ‘faces’ or ‘triangles’, less about vertices or planes i guess.

The easiest way would be to keep the original data. It's still useful e.g. for collision detection so you don't want to break anything here.

First look what a draw call is. Is it a single triangle, or all triangles of a convex cell? In any case, that's where you can get the data, subivide it and draw that instead. You can do this per frame at first to get going. Try to draw Points at vertices ("debug visualization"), and lines at edges, to verify visually. Then draw an extra vertex at the edges midpoints, add edges and so on. Then you can think of how to store the new data, do it just once at level load, how to link it to the original draw calls, etc.

If you don't have a way to draw such debug visualization yet, work on this first. Ability to draw points and lines from anywhere in the code gives you feedback on correctness of geometric assumptions, or lets you figure out what a certain piece of code is doing. It helps with any kind of doubts and uncertainty - very important for both learning and debugging.

Tip: Because it may conflict with render states, it works best to have buffers for points, lines, triangles. std::vector would be fine to get going.

Here is a piece of what i'm using. Ignore how messy this is, but you get the idea…

	void RenderPoint (float *v1, float *color)
	{
		if (numVertices[POINTS]+1 >= VERTEX_LIST_SIZE) return;	
			vertices[POINTS][numVertices[POINTS]++].Set (v1, color); 
	}

	void RenderLine (float *v1, float *v2, float *color)
	{
		if (numVertices[LINES]+2 >= VERTEX_LIST_SIZE*2) return;		
			vertices[LINES][numVertices[LINES]++].Set (v1, color); 
			vertices[LINES][numVertices[LINES]++].Set (v2, color); 
	}

	void RenderTriangle (float *v1, float *v2, float *v3, float *color)
	{
		if (numVertices[TRIANGLES]+3 >= VERTEX_LIST_SIZE*3) return;		
			vertices[TRIANGLES][numVertices[TRIANGLES]++].Set (v1, color); 
			vertices[TRIANGLES][numVertices[TRIANGLES]++].Set (v2, color); 
			vertices[TRIANGLES][numVertices[TRIANGLES]++].Set (v3, color); 
	}

And i have something with more comfort on top of that, which looks like this:

	inline void RenderLine (sVec3 pos1, sVec3 pos2, float r, float g, float b, float a=1.0)
	{
		float col[4] = {r,g,b,a};
		simpleVis.RenderLine (&pos1[0], &pos2[0], col);
	}
	inline void RenderVector (sVec3 pos, sVec3 vec, float r, float g, float b, float a=1.0)
	{
		RenderLine (pos, sVec3(pos + vec), r, g, b, a);
	}
	inline void RenderTriangle (sVec3 pos1, sVec3 pos2, sVec3 pos3, float r, float g, float b, float a=1.0)
	{
		float col[4] = {r,g,b,a};
		simpleVis.RenderTriangle (&pos1[0], &pos2[0], &pos3[0], col);
	}

… so i push such points from anywhere in the code, and render it after the frame is done on top, and resetting the buffers for the next frame. Very helpful.

Tom_W said:
Trying HLSL isn't getting me far(though I haven't really gotten that far into it yet. I've considered upgrading to DX11, but my thinking behind staying with DX9

Just stick at it. Shaders seem not important yet for you - it's more likely distracting. DX9 or 11… who cares, it's just output but not really the game.

Thanks Joe! I always give you an extra heart for every reply ?
But .Set? What's that? DirectX9 has no such struct/class member, I'm guessing this is for DX10/11. Is it? Because damn if you don't even have to call DrawPrimative then it must be an easier API…

Set() is just i function i use to copy vertex data to the buffer. I only wanted to show how the interface could look like. Some more complete old school OpenGL pseudo code would be:

class Vis
{
static std::vector<float> buffer;

public:
static void DrawPoint(float *pos, float *col)
{
buffer.push_back(pos[0]);
buffer.push_back(pos[1]);
buffer.push_back(pos[2]);
buffer.push_back(col[0]);
buffer.push_back(col[1]);
buffer.push_back(col[2]);
} 

static void DrawFrame()
{
glPointSize(5);
glBegin(GL_POINTS);
for (int i=0; i<buffer.size(); i+=6)
{
glColor3fv(buffer.data()+i+3);
glVertex3fv(buffer.data()+i);
}
glEnd();
buffer.clear();
}

};

So, from anywhere in your code you could do things like

Vis::DrawPoint(myVertex.pos, 1,0,0);

And after the frame is done call

Vis::DrawFrame();

Then you can check visually if the red point appears where you assumed it to be…

Hey, I'm bumping the thread because it seems I am not content without HLSL per pixel lighting. My game engine so far(VERY hard coded and code is sloppy, sue me, I'm not at the show-off phase yet :P :

I've managed to render a simple textured cube, import a shader called “blinn_phong.fx”, and apply the effect properly to the cube. However, that can not be said for ANY of the other prims in my game. I created the effect, g_pEffect, filled in the information, works great on the cube. But when I created an extra argument for the effect to passed to the DrawFace() function of my BSP header file, LITERALLY NOTHING DRAWS. Not even a prim without a texture, in wireframe mode there's nothing – I mean literally nothing is drawn.

I loaded the shader, blinn_phong.fx:

//-----------------------------------------------------------------------------
// Copyright (c) 2006-2008 dhpoware. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//
// This D3DX Effect file contains HLSL shaders that implement per-pixel
// Blinn-Phong and Phong lighting by evaluating Direct3D's fixed function
// lighting model per-pixel.
//
// Direct3D's fixed function lighting model is described here:
//  DirectX Documentation for C++ > DirectX Graphics > Direct3D 9 >
//  Programming Guide > Getting Started > Lights and Materials >
//  Mathematics of Lighting.
//
// All lighting calculations are performed in world space.
//
// The shaders in this effect file only support a single material and light
// source. However it should be relatively straight forward to generalize these
// shaders to support multiple lights and materials.
//
// We use a simplified version of the Direct3D fixed function spot lighting
// model in the shaders in this effect file. The simplified version produces a
// more visually appealing spotlight effect compared to a direct per-pixel
// implementation of the fixed function model.
//
// Light attenuation for the point and spot lighting models is based on a
// light radius. Light is at its brightest at the center of the sphere defined
// by the light radius. There is no lighting at the edges of this sphere.
//
//-----------------------------------------------------------------------------

struct Light
{
float3 dir;                     // world space direction
float3 pos;                     // world space position
float4 ambient;
float4 diffuse;
float4 specular;
float spotInnerCone;            // spot light inner cone (theta) angle
float spotOuterCone;            // spot light outer cone (phi) angle
float radius;                   // applies to point and spot lights only
};

struct Material
{
float4 ambient;
float4 diffuse;
float4 emissive;
float4 specular;
float shininess;
};

//-----------------------------------------------------------------------------
// Globals.
//-----------------------------------------------------------------------------

float4x4 worldMatrix;
float4x4 worldInverseTransposeMatrix;
float4x4 worldViewProjectionMatrix;

float3 cameraPos;
float4 globalAmbient;

Light light;
Material material;

//-----------------------------------------------------------------------------
// Textures.
//-----------------------------------------------------------------------------

texture colorMapTexture;

sampler2D colorMap = sampler_state
{
Texture = <colorMapTexture>;
   MagFilter = Linear;
   MinFilter = Anisotropic;
   MipFilter = Linear;
   MaxAnisotropy = 16;
};

//-----------------------------------------------------------------------------
// Vertex Shaders.
//-----------------------------------------------------------------------------

struct VS_INPUT
{
float3 position : POSITION;
float2 texCoord : TEXCOORD0;
float3 normal : NORMAL;
};

struct VS_OUTPUT_DIR
{
float4 position : POSITION;
float2 texCoord : TEXCOORD0;
float3 halfVector : TEXCOORD1;
float3 lightDir : TEXCOORD2;
float3 normal : TEXCOORD3;
float4 diffuse : COLOR0;
float4 specular : COLOR1;
};

struct VS_OUTPUT_POINT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD0;
float3 viewDir : TEXCOORD1;
float3 lightDir : TEXCOORD2;
float3 normal : TEXCOORD3;
float4 diffuse : COLOR0;
float4 specular : COLOR1;
};

struct VS_OUTPUT_SPOT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD0;
float3 viewDir : TEXCOORD1;
float3 lightDir : TEXCOORD2;
float3 spotDir : TEXCOORD3;
float3 normal : TEXCOORD4;
float4 diffuse : COLOR0;
float4 specular : COLOR1;
};

VS_OUTPUT_DIR VS_DirLighting(VS_INPUT IN)
{
VS_OUTPUT_DIR OUT;

float3 worldPos = mul(float4(IN.position, 1.0f), worldMatrix).xyz;
float3 viewDir = cameraPos - worldPos;
 
OUT.position = mul(float4(IN.position, 1.0f), worldViewProjectionMatrix);
OUT.texCoord = IN.texCoord;
OUT.lightDir = -light.dir;
OUT.halfVector = normalize(normalize(OUT.lightDir) + normalize(viewDir));
OUT.normal = mul(IN.normal, (float3x3)worldInverseTransposeMatrix);
OUT.diffuse = material.diffuse * light.diffuse;
OUT.specular = material.specular * light.specular;
       
return OUT;
}

VS_OUTPUT_POINT VS_PointLighting(VS_INPUT IN)
{
VS_OUTPUT_POINT OUT;

float3 worldPos = mul(float4(IN.position, 1.0f), worldMatrix).xyz;
   
OUT.position = mul(float4(IN.position, 1.0f), worldViewProjectionMatrix);
OUT.texCoord = IN.texCoord;
OUT.viewDir = cameraPos - worldPos;
OUT.lightDir = (light.pos - worldPos) / light.radius;
OUT.normal = mul(IN.normal, (float3x3)worldInverseTransposeMatrix);
OUT.diffuse = material.diffuse * light.diffuse;
OUT.specular = material.specular * light.specular;
 
return OUT;
}

VS_OUTPUT_SPOT VS_SpotLighting(VS_INPUT IN)
{
   VS_OUTPUT_SPOT OUT;
   
   float3 worldPos = mul(float4(IN.position, 1.0f), worldMatrix).xyz;
       
   OUT.position = mul(float4(IN.position, 1.0f), worldViewProjectionMatrix);
OUT.texCoord = IN.texCoord;
OUT.viewDir = cameraPos - worldPos;
OUT.lightDir = (light.pos - worldPos) / light.radius;
   OUT.spotDir = light.dir;
   OUT.normal = mul(IN.normal, (float3x3)worldInverseTransposeMatrix);
   OUT.diffuse = material.diffuse * light.diffuse;
OUT.specular = material.specular * light.specular;
       
   return OUT;
}

//-----------------------------------------------------------------------------
// Pixel Shaders.
//-----------------------------------------------------------------------------

float4 PS_DirLighting(VS_OUTPUT_DIR IN) : COLOR
{
   float3 n = normalize(IN.normal);
   float3 h = normalize(IN.halfVector);
   float3 l = normalize(IN.lightDir);
   
   float nDotL = saturate(dot(n, l));
   float nDotH = saturate(dot(n, h));
   float power = (nDotL == 0.0f) ? 0.0f : pow(nDotH, material.shininess);    

float4 color = (material.ambient * (globalAmbient + light.ambient)) +
                  (IN.diffuse * nDotL) + (IN.specular * power);

return color * tex2D(colorMap, IN.texCoord);
}

float4 PS_PointLighting(VS_OUTPUT_POINT IN) : COLOR
{
   float atten = saturate(1.0f - dot(IN.lightDir, IN.lightDir));

float3 n = normalize(IN.normal);
   float3 l = normalize(IN.lightDir);
   float3 v = normalize(IN.viewDir);
   float3 h = normalize(l + v);
   
   float nDotL = saturate(dot(n, l));
   float nDotH = saturate(dot(n, h));
   float power = (nDotL == 0.0f) ? 0.0f : pow(nDotH, material.shininess);
   
float4 color = (material.ambient * (globalAmbient + (atten * light.ambient))) +
                  (IN.diffuse * nDotL * atten) + (IN.specular * power * atten);
                   
return color * tex2D(colorMap, IN.texCoord);
}

float4 PS_SpotLighting(VS_OUTPUT_SPOT IN) : COLOR
{
   float atten = saturate(1.0f - dot(IN.lightDir, IN.lightDir));
   
float3 l = normalize(IN.lightDir);
   float2 cosAngles = cos(float2(light.spotOuterCone, light.spotInnerCone) * 0.5f);
   float spotDot = dot(-l, normalize(IN.spotDir));
   float spotEffect = smoothstep(cosAngles[0], cosAngles[1], spotDot);
   
   atten *= spotEffect;
                               
   float3 n = normalize(IN.normal);
float3 v = normalize(IN.viewDir);
float3 h = normalize(l + v);
   
   float nDotL = saturate(dot(n, l));
   float nDotH = saturate(dot(n, h));
   float power = (nDotL == 0.0f) ? 0.0f : pow(nDotH, material.shininess);
   
   float4 color = (material.ambient * (globalAmbient + (atten * light.ambient))) +
                  (IN.diffuse * nDotL * atten) + (IN.specular * power * atten);
   
return color * tex2D(colorMap, IN.texCoord);
}

//-----------------------------------------------------------------------------
// Techniques.
//-----------------------------------------------------------------------------

technique PerPixelDirectionalLighting
{
pass
{
 VertexShader = compile vs_2_0 VS_DirLighting();
 PixelShader = compile ps_2_0 PS_DirLighting();
}
}

technique PerPixelPointLighting
{
   pass
   {
       VertexShader = compile vs_2_0 VS_PointLighting();
       PixelShader = compile ps_2_0 PS_PointLighting();
   }
}

technique PerPixelSpotLighting
{
   pass
   {
       VertexShader = compile vs_2_0 VS_SpotLighting();
       PixelShader = compile ps_2_0 PS_SpotLighting();
   }
}

And then used LoadShader() to load it:

 if (!LoadShader("blinn_phong.fx", g_pEffect))
 ErrMsg("Could not load shader blinn_phong.fx.");

Then used the function UpdateEffect() to fill in all the arguments for the shader:

void UpdateEffect()
{

static D3DXMATRIX xRot, yRot;
static D3DXMATRIX worldViewProjectionMatrix;
static D3DXMATRIX worldInverseTransposeMatrix;

/* D3DXMatrixPerspectiveFovLH(&proj, CAMERA_FOVY,
static_cast<float>(g_windowWidth) / static_cast<float>(g_windowHeight),
CAMERA_ZNEAR, CAMERA_ZFAR);

D3DXMatrixLookAtLH(&view, &g_cameraPos, &g_targetPos, &D3DXVECTOR3(0.0f, 1.0f, 0.0f));*/

// Calculate world matrix.
//D3DXMatrixRotationX(&xRot, D3DXToRadian(g_pitch));
//D3DXMatrixRotationY(&yRot, D3DXToRadian(g_heading));
//D3DXMatrixMultiply(&world, &yRot, &xRot);

// Calculate combined world-view-projection matrix.
worldViewProjectionMatrix = world * view * proj;

// Calculate inverse-transpose world matrix.
D3DXMatrixInverse(&worldInverseTransposeMatrix, 0, &world);
D3DXMatrixTranspose(&worldInverseTransposeMatrix, &worldInverseTransposeMatrix);
float                        g_sceneAmbient[4] = { 0.2f, 0.2f, 0.2f, 1.0f };
// Set the matrices for the shader.
g_pEffect->SetMatrix("worldMatrix", &world);
g_pEffect->SetMatrix("worldInverseTransposeMatrix", &worldInverseTransposeMatrix);
g_pEffect->SetMatrix("worldViewProjectionMatrix", &worldViewProjectionMatrix);
float ambient[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
float diffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
float specular[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
//0.508273f, 0.508273f, 0.508273f, 1.0f,  // specular
float shininess = 51.2f;
float emissive[4] = {0.0f, 0.0f, 0.0f, 1.0f};                 // emissive// shininess
D3DXVECTOR3 temppos = { 0.0f, 0.0f, 0.0f };
D3DXVECTOR3 tempdir = { 0.0f, 0.0f, 0.0f };
// Set the camera position.
g_pEffect->SetValue("cameraPos", &g_vCamPosition, sizeof(&g_vCamPosition));

// Set the scene global ambient term.
g_pEffect->SetValue("globalAmbient", &g_sceneAmbient, sizeof(g_sceneAmbient));

// Set the lighting parameters for the shader.
g_pEffect->SetValue("light.dir", g_vCamDir, sizeof(g_vCamDir));
g_pEffect->SetValue("light.pos", g_vCamPosition, sizeof(g_vCamPosition));
g_pEffect->SetValue("light.ambient", ambient, sizeof(ambient));
g_pEffect->SetValue("light.diffuse", diffuse, sizeof(diffuse));
g_pEffect->SetValue("light.specular", specular, sizeof(specular));
g_pEffect->SetFloat("light.spotInnerCone", D3DXToRadian(90.0f));
g_pEffect->SetFloat("light.spotOuterCone", D3DXToRadian(80.0f));
g_pEffect->SetFloat("light.radius", 40);

// Set the material parameters for the shader.
g_pEffect->SetValue("material.ambient", ambient, sizeof(ambient));
g_pEffect->SetValue("material.diffuse", diffuse, sizeof(diffuse));
g_pEffect->SetValue("material.emissive", emissive, sizeof(emissive));
//g_pEffect->SetValue("material.specular", shininess, sizeof(51.2f);

// Bind the textures to the shader.
//if (g_disableColorMapTexture)
 //g_pEffect->SetTexture("colorMapTexture", cubetex);
//else
 //g_pEffect->SetTexture("colorMapTexture", g_pColorMapTexture);
}

(The world matrix is set in a prior function, hence why it is commented out in this function)

And then, I draw the cube:

UpdateEffect();
static UINT totalPasses;
static D3DXHANDLE hTechnique;
hTechnique = g_pEffect->GetTechniqueByName("PerPixelSpotLighting");
//hTechnique = g_pEffect->GetTechniqueByName("PerPixelDirectionalLighting");
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTexture(0, cubetex);
g_pd3dDevice->SetVertexDeclaration(g_pVertexDecl);
g_pd3dDevice->SetStreamSource(0, g_pVertexBuffer, 0, sizeof(Vertex));
// Render the cube.
if (SUCCEEDED(g_pEffect->SetTechnique(hTechnique)))
{
 if (SUCCEEDED(g_pEffect->Begin(&totalPasses, 0)))
 {
  for (UINT pass = 0; pass < totalPasses; ++pass)
  {
   if (SUCCEEDED(g_pEffect->BeginPass(pass)))
   {
    g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 12);
    g_pEffect->EndPass();
   }
  }

  g_pEffect->End();
 }
}
//g_pd3dDevice->SetStreamSource(0, 0, 0, 0);
//g_pd3dDevice->SetTexture(0, 0);
}

Which works perfectly. For a cube. Now, in DrawFace(), I added a pointer argument to the function so I could pass the effect to it, the function is as follows:

void DrawFace(IDirect3DDevice9 * pDevice,
 int nFace, D3DXHANDLE hTechnique, ID3DXEffect *pEffect)
{

 pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
 pDevice->SetRenderState(D3DRS_DITHERENABLE, true);
 //pDevice->SetRenderState(D3DRS_FOGENABLE, true);
 //pDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG2);
 pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
 pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
 //pDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_DIFFUSE);
 //pDevice->SetTextureStageState(0,D3DTSS_COLORARG2, D3DTA_TEXTURE);
// pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
 //pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
 //pDevice->SetRenderState(D3DRS_WRAP0, D3DWRAPCOORD_0);
 //pDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_PHONG);
 //pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
 //pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);  

 pDevice->SetIndices(m_pIB);

 pDevice->SetStreamSource(0, m_pVB, 0, sizeof(stBSPVertex));

 pDevice->SetFVF( m_FVF_Format );

 // If its not a tri mesh
 if( m_pFaces[nFace].nFaceType != 1)return;
 
 int nFirstF = m_pFaces[nFace].nFirstMeshVerts;
 int nNumF   = m_pFaces[nFace].NumMeshVerts;

 int nFirstV = m_pFaces[nFace].FirstVert;
 int nNumV   = m_pFaces[nFace].NumVerts;

 int nTexIndex = m_pFaces[nFace].nTexture;

 pDevice->SetTexture( 0, m_pT[nTexIndex] );
 pEffect->SetTexture(0, m_pT[nTexIndex]);
 int nNumTris = nNumF / 3;

 /*
 pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,  // Type
                        nFirstV,    // BaseVertexIndex
         0,      // MinIndex
         nNumV,     // NumVertices
         nFirstF,    // StartIndex
         nNumTris );    // PrimitiveCount
 */

 m_nNumTrisDraw += (m_pFaces[nFace].NumMeshVerts/3);
 static UINT totalPasses;
//  static D3DXHANDLE hTechnique;
 //hTechnique = pEffect->GetTechniqueByName("PerPixelSpotLighting");
 //char buff[100];
 //sprintf(buff, "%f", pEffect->GetValue())
 hTechnique = pEffect->GetTechniqueByName("PerPixelDirectionalLighting");
 
 // Render the cube.
 /*if (SUCCEEDED(pEffect->SetTechnique(hTechnique)))
 {
   
  if (SUCCEEDED(pEffect->Begin(&totalPasses, 0)))
  {
   for (UINT pass = 0; pass < totalPasses; ++pass)
   {
    if (SUCCEEDED(pEffect->BeginPass(pass)))
    {*/
     pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,  //THIS WON'T EVEN DRAW!!!! I'VE CHECKED IF pEffect SUCCEDED AND IT DOES!!! WTF AM I MISSING? Everything probably.
      m_pFaces[nFace].FirstVert,
      0,
      m_pFaces[nFace].NumVerts,
      m_pFaces[nFace].nFirstMeshVerts,
      (m_pFaces[nFace].NumMeshVerts / 3));
    // pEffect->EndPass();
    //}
   //}

   //pEffect->End();
  //}
 //}


}

I commented out the passes because all I get is BLACK. Nothing. No map. No prims are drawn whatsoever, and I've been at this HLSL thing for a while now. I really need your guy's expertise on this. Again, I am not well versed in DirectX, so please try to baby me with your responses. I'm obviously missing something massive. This is all new to me. I'd really really appreciate some help on this, and you know what, if someone flat out comes out with an easy to understand answer that solves this and wants my original “bounty” or “payment” for your help I won't hesitate to throw a hundred bucks your way ?

Sorry to bump the thread, but I'd really appreciate some help on this subject. I'm having a hard time applying HLSL to any other prims other than a simple cube – all part of the same world matrix; I've tried everything, from passing the effect as a pointer, to having my BSP class have its own shader loading and effect function. If some genius like Joe or others could help me out, I'd be much obliged..

The problem is you want us to help you with issues that require understanding your code base. That's not really possible from a distance just by browsing thousands lines of code. Maybe somebody with DirectX experience can spot something by luck, but the code you show here is a lot, and the problem may be somewhere else.

This “It's just black! Why???” thing happens often and it sucks. Do you check Error states provided by DirectX? Do you use gfx debugging tools like Nsight, Pix, something is built in into Visual Studio…, stuff like that? (Error checks is surely worth it, debug tools are not easy to use themselves…)


@JoeJ Thank you for your support. I just want to clarify – that no matter what, when any prim is drawn, whether it's DrawIndexedPrimated of DrawPrimative/etc, regardless of the function, if there is an effect and the prim drawing function is within the loop of passes, a shader should work if configured properly? Again, it's my lack of fundamental understanding of shaders that is the issue here.

thanks Joe <3

I've gotten it now, thank you Joe, and everyone else. HLSL is awesome. Problem is now they completely decimated my matrices for all my map objects that are meshes(they're in different locations or completely disappeared, I had to add a shader for them as well because meshes with textures apparently won't show if you're using a shader in the same matrix they're in and they're not rendered using a similar shader), but I'm sure I can correct that problem. Thanks all!

This topic is closed to new replies.

Advertisement