directx - Billboard using the Geometry shader -


i trying render billboards using geometry-shader takes points input , outputs triangle stream (using directx11). current result not expect be.

for comparison, here 2 screenshots, rendering same set of particles, viewed same direction (more or less, had rotate camera ~90°) , distance, once rendered points , once rendered billboard shader:

particles rendered billboard shader particles rendered points

as can see in second picture, when rendered points, 1 can see particles' moving away center, covering entire screen, whereas when rendered billboard shader, change in scale slightly, remain stationary.

unfortunately, don't have clue causing this. i've been following tutorials such this, explains how matrix supposed set-up, result shows either expectations or implementation wrong.

the following code billboard shader, builds matrix describe particle's orientation , emits 2 triangles billboard:

#include <materials/sceneconstants.hlsl> #include <materials/modelconstants.hlsl> #include <particles/particle.hlsl>  texture2d diffusetexture : register(ps, t[0]); samplerstate diffusesampler : register(ps, s[0]);  struct ps_in {     float4 position : sv_position;     float4 color : color;     float2 texcoord : texcoord; };  particle vs(particle input) {     return input; }  [maxvertexcount(4)] void gs(point particle particles[1], inout trianglestream<ps_in> tristream) {     // need create matrix local coordinate system billboard of given particle.     // 1 axis points particle camera, 1 axis camera's side axis (for example     // left) , third 1 perpendicular both.     particle particle = particles[0];      float3 zaxis = normalize(cameraposition - particle.position);     float3 xaxis = normalize(cross(float3(0, 1, 0), zaxis));     float3 yaxis = cross(zaxis, xaxis);      // matrix describe local coordinate system constructed:     float4x4 localtoworld;     localtoworld._11 = xaxis.x;     localtoworld._21 = xaxis.y;     localtoworld._31 = xaxis.z;     localtoworld._12 = yaxis.x;     localtoworld._22 = yaxis.y;     localtoworld._32 = yaxis.z;     localtoworld._13 = zaxis.x;     localtoworld._23 = zaxis.y;     localtoworld._33 = zaxis.z;     localtoworld._41 = particle.position.x;     localtoworld._42 = particle.position.y;     localtoworld._43 = particle.position.z;     localtoworld._14 = 0;     localtoworld._24 = 0;     localtoworld._34 = 0;     localtoworld._44 = 1;      // , matrix transform local screen space...     float4x4 transform = localtoworld * world * viewprojection;      // positions of quad described in local coordinate system:     // -z points towards camera, y points upwards , x towards right.     // position marks center of quad, hence (0, 0, 0) center of quad in     // local coordinates , quad has edge-length of particle.size either side.     ps_in v1, v2, v3, v4;     //float size = particle.size / 2;     float size = 0.5f;     v1.position = mul(float4(-size, size, 0, 1), transform);     v1.texcoord = float2(0, 0);     v1.color    = particle.color;     v2.position = mul(float4(size, size, 0, 1), transform);     v2.texcoord = float2(1, 0);     v2.color    = particle.color;     v3.position = mul(float4(-size,-size, 0, 1), transform);     v3.texcoord = float2(0, 1);     v3.color    = particle.color;     v4.position = mul(float4(size, -size, 0, 1), transform);     v4.texcoord = float2(1, 1);     v4.color    = particle.color;      tristream.append(v1);     tristream.append(v2);     tristream.append(v3);     tristream.append(v4); }  float4 ps(ps_in input) : sv_target0 {     /*float4 texel = diffusetexture.sample(diffusesampler, input.texcoord);     return input.color * texel;*/     return float4(1, 1, 1, 1); } 

for reference, here shader-code rendering particles simple points well:

#include <materials/sceneconstants.hlsl> #include <materials/modelconstants.hlsl> #include <particles/particle.hlsl>   struct ps_in {     float4 position : sv_position;     float4 color : color; };  ps_in vs(particle input) {     ps_in output;      float4 posworld = mul(float4(input.position, 1), world);     output.position = mul(posworld, viewprojection);     output.color = input.color;      return output; }  float4 ps(ps_in input) : sv_target0 {     //return input.color;     return float4(1, 1, 1, 1); } 

another oddity noticed billboards not facing camera, @ least not always. way setup matrix, expect them to, however. instead, face camera when viewed 2 opposing directions, , decrease in width begin rotate camera.

this led me believe made mistake building matrix, unable spot it.

hopefully guys can me find problem. in advance help!

edit

i seem have found solution problem, not understand why one. bizarre reason, cannot multiply localtoworld matrix viewprojection matrix. instead, have separate 2 steps so:

v1.position = mul(float4(-size, size, 0, 1), localtoworld); v1.position = mul(v1.position, viewprojection); 

i not understand why case, maybe it's connected using row_major matrices instead of default, column_major. now, behaviour not make sense me, @ all: matrix multiplication should associative, , therefore snippet above should result in same outcome original code, not. maybe of can shed light on going on here.

i think have translation vector in wrong part of matrix, should read

localtoworld._14 = particle.position.x; localtoworld._24 = particle.position.y; localtoworld._34 = particle.position.z; localtoworld._41 = 0; localtoworld._42 = 0; localtoworld._43 = 0; 

Comments

Popular posts from this blog

java - Jmockit String final length method mocking Issue -

asp.net - Razor Page Hosted on IIS 6 Fails Every Morning -

c++ - wxwidget compiling on windows command prompt -