vprat

Members
  • Content count

    21
  • Joined

  • Last visited

Community Reputation

122 Neutral

About vprat

  • Rank
    Member
  1. Hi, thanks for the papers, I read them and it was very interesting. So following your advice and as you gave me a new idea, I have today given a try to a 3rd possible implementation using geometry instancing (basically sending the whole mesh + an instance buffer containing the cube face index then a GS chooses the render target). I have as well optimised the other two implementations as well. My conclusion on my small test scene is that the two single pass algorithms are a bit faster than the multi-pass (as expected and unlike in the previous unoptimized implementations). I had never thought about using geometry instancing for rendering a cube map in a single pass. That's a neat application. (however not applicable to DX9 because you need the GS to direct the primitive to the right render target). For the ones who would like to have more info, on the dev blog of Kourjet. I will leave the other experimentations you mention (clipping planes and so on) for later in order to concentrate now on directional lights and spot lights :) Thanks a lot, regards,
  2. Update: I gave it a try and finally implemented a solution that allows to switch between single/multi pass rendering of the cube map. I must say that the single pass rendering algorithm still wins (75 vs 45 frames per seconds) even though I do culling and output only the required primitives in the geometry shader. More about the implementations on the Kourjet Engine blog Could this be because my graphics card is not so great? (NVidia GeForce 9M series, acer laptop)
  3. Hi, thanks for the reply. I keep my current multiple pass rendering as it is for now. and I will try to further optimize the single pass rendering then. So if I understand well, what could be done for one point light is: set cube as 6 render targets at once get objects within light range for each object within range do frustum test against the 6 frusta of the cube map set flags in the effect to indicate which planes to render to render the object to the cube map in single pass and the geometry shader could be something like: // For each face of the cube //-- for( int f = 0; f < 6; ++f ) { // Check the write to face flag //-- if ( writeToFace[f]==true ) { GS_CUBEPL_OUTPUT output = (GS_CUBEPL_OUTPUT) 0; // Assign triangle to the RT corresponding to this cube face //-- output.RTIndex = f; for( int v = 0; v < 3; v++ ) { output.position = mul( input[v].position, kgfx_matViewProj[f] ); output.light = input[v].position.xyz - kgfx_vLightPosition; CubeMapStream.Append( output ); } CubeMapStream.RestartStrip(); } } } However I don't really see where I would use SV_ClipDistance or SV_Cull. Is there a better way than the above with those techniques? Would you happen to have the link to the white papers you are mentioning (or the title or any additional info to help me find it). I found some paper mentioning how to do frustum culling inside the GS. However it looks rather inefficient to do it per primitive instead of doing it against a bounding sphere before. [Edited by - vprat on November 29, 2009 7:40:16 AM]
  4. Hi, I am currently implementing point light shadow mapping. I have so far successfully implemented 2 ways to do it: - Single pass cube map rendering using geometry shader (my 1st implementation) - Multi pass rendering (my 2nd implementation) I have implemented the second one because it allows me to do culling per cube face. I am seeing great improvements with this method and I want to try to optimize it. I am trying to minimise render target changes. With the first method, only one change per light (worst case). In the second method, 6 changes (worst case, could be less if culling returned no object for a face). So my idea would be to set the 6 render targets at once (just like the first method) and using an effect parameter, select the appropriate render target to write to. I could not do it with SV_TARGETn (because this is static, you need to know at compilation time to which target you'll be writing to). I also tried a if ( face==N ) output.colorN = ...; but I don't like the 6 if cases. I would need something in the pixel shader like output.color[ face ] = ...; where face is an effect variable set just before pass.apply() Is this possible?
  5. Hi, I got it working properly. One thing was the reflect vector being inverted. Other thing was that in my sampling of the normal map I had a float being implicitly casted to a float3 but not as expected so the line: N = normalize( 2.0 * kgfx_texNormalMap.Sample( linearSampler, input.texCoord ) - 1.0 ); was corrected into: N = normalize( 2.0 * kgfx_texNormalMap.Sample( linearSampler, input.texCoord ) - float3( 1, 1, 1 ) ); I also removed most normalisation from the VS and some from the PS and took a normal map in the PNG format (JPEG showed the compression artifacts). Thanks a lot for helping, very appreciated. For those who could be interested, here is the final code: //---------------------------------------------------------------------------- // Types //---------------------------------------------------------------------------- struct VS_INPUT { float3 position : POSITION; float3 normal : NORMAL; float2 texCoord : TEXCOORD0; float4 tangent : TANGENT; }; struct VS_OUTPUT { float4 position : SV_POSITION; float2 texCoord : TEXCOORD0; float3 view : TEXCOORD1; float3 light : TEXCOORD2; }; struct PS_OUTPUT { float4 color : SV_TARGET; }; //---------------------------------------------------------------------------- // Shaders //---------------------------------------------------------------------------- VS_OUTPUT myVertexShader( VS_INPUT input, uniform bool bWireframe = false ) { VS_OUTPUT output = (VS_OUTPUT) 0; // Some vectors in world space //-- float4 P = mul( float4( input.position, 1), kgfx_matWorld ); // Position in world space float3 L = kgfx_vLightPosition.xyz - P.xyz; // Light in world space float3 V = kgfx_vCameraPosition.xyz - P.xyz; // View in world space float3 T = mul( input.tangent, (float3x3) kgfx_matWorld ); float3 N = mul( input.normal, (float3x3) kgfx_matWorld ); float3 B = input.tangent.w * cross( N, T ); // Built the TBN matrix (world to texture space transform) //-- float3x3 TBN; TBN[0] = T; TBN[1] = B; TBN[2] = N; output.position = mul( P, kgfx_matViewProj ); // Position in screen space output.texCoord = input.texCoord; // Copy tex coords output.light = mul( TBN, L ); // Light in texture space output.view = mul( TBN, V ); // View in texture space return output; } PS_OUTPUT myPixelShader( VS_OUTPUT input, uniform bool bWireframe = false ) { PS_OUTPUT output = (PS_OUTPUT) 0; // Compute pixel value //-- if ( bWireframe ) { output.color = kgfx_colColor; } else { float3 L = normalize( input.light ); float3 V = normalize( input.view ); float3 N = float3( 0, 0, 1 ); float fSelfShadow = dot( N, L ); if ( kgfx_bUseNormalMap>0 && fSelfShadow>=0 ) { N = normalize( 2.0 * kgfx_texNormalMap.Sample( linearSampler, input.texCoord ) - float3( 1, 1, 1 ) ); } fSelfShadow = saturate( 10 * fSelfShadow ); float3 R = reflect( -L, N ); float fSpecular = pow( saturate( dot( R, V ) ), 60 ); float fDiffuse = saturate( dot( N, L ) ); float4 colColor = kgfx_bUseColorMap<=0 ? kgfx_colColor : kgfx_texColorMap.Sample( linearSampler, input.texCoord ); output.color.rgb = fSelfShadow * ( fDiffuse * colColor.rgb + fSpecular * kgfx_colLightColor.rgb ); output.color.a = colColor.a; } return output; }
  6. Hi, First of all, thanks a lot for your input. It works indeed when inverting the reflection vector. Why is this vector inverted? I have never seen in the other tutorials any -reflect( L, N ). Is it a problem with my tangent space calculations? Also, the shader works well without any normal mapping (N = 0, 0, 1) but not any more when I fetch the normal from the normal map. The normal map texture is created in the format R8G8B8A8_UNORM and is a normal map taken from blender I think so should be a valid file.
  7. Hi, I am currently implementing per pixel phong shading + normal mapping using DX10 and HLSL. I have the diffuse + normal map component working, but I am having problems with the specular component. First a picture of my result: As you can see, the specular result is as if the viewer or the light was on the left side of the cube. The diffuse result shows what is correct. As my diffuse-only result is fine, I assume the tangent space calculations are correct (maybe I am wrong). So I am left with a problem most probably with the reflection vector calculation or the view vector calculation. Below is the relevant code for the sample. I have generated a cube (but have same results with sphere and plane) where the front face (-z as normal) is generated like this: // Normal is -Z axis // Tangent is X axis // Tangent.w is -1 so that the binormal is correct //-- pVertex->vPosition = CVector3( fWidth * ( u - 0.5f ), fHeight * ( v - 0.5f ), -0.5f * fDepth ); pVertex->vNormal = CVector3( 0.0f, 0.0f, -1.0f ); pVertex->vTangent = CVector4( 1.0f, 0.0f, 0.0f, -1.0f ); pVertex->vTexCoord = CVector2( u, 1.0f - v ); My vertex shader is the following: VS_OUTPUT output = (VS_OUTPUT) 0; // Some vectors in world space //-- float4 P = mul( float4( input.position, 1), kgfx_matWorld ); // Position in world space float3 L = normalize( kgfx_vLightPosition.xyz - P.xyz ); // Light in world space float3 V = normalize( kgfx_vCameraPosition.xyz - P.xyz ); // View in world space // Build world to tangent space transformation //-- float3 T = normalize( mul( input.tangent, (float3x3) kgfx_matWorld ) ); float3 N = normalize( mul( input.normal, (float3x3) kgfx_matWorld ) ); float3 B = normalize( input.tangent.w * cross( N, T ) ); float3x3 TBN; TBN[0] = T; TBN[1] = B; TBN[2] = N; // Build the output //-- output.position = mul( P, kgfx_matViewProj ); // Position in screen space output.texCoord = input.texCoord; // Copy tex coords output.light = normalize( mul( TBN, L ) ); // Light in texture space output.view = normalize( mul( TBN, V ) ); // View in texture space return output; My pixel shader is the following: float3 L = normalize( input.light ); // Light in tangent space float3 V = normalize( input.view ); // View in tangent space float3 N = float3( 0, 0, 1 ); // Default normal in tangent space to compute self shadowing float fSelfShadow = dot( N, L ); if ( fSelfShadow>=0 ) { // Get normal from normal map //-- N = normalize( 2.0 * kgfx_texNormalMap.Sample( linearSampler, input.texCoord ) - 1.0 ); } fSelfShadow = saturate( 10 * fSelfShadow ); // Light reflection vector //-- float3 R = normalize( reflect( L, N ) ); float fSpecular = pow( saturate( dot( R, V ) ), 60 ); float fDiffuse = saturate( dot( N, L ) ); float4 colColor = kgfx_texColorMap.Sample( linearSampler, input.texCoord ); output.color = fSelfShadow * ( fDiffuse * colColor + fSpecular * kgfx_colLightColor );