Matrix mapping error in vertex shader code in DirectX9 - hlsl

In my DirectX9 sample when I do the below things all works fine and I get the desired rotating triangle on screen,
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
But when I try to do the same using shaders nothing gets rendered
D3DXMATRIXA16 matWorldViewProj = matWorld * matView * matProj;
constantTable->SetMatrix(g_pd3dDevice, "g_mWorldViewProjection", &matWorldViewProj);
//Vertex Shader snippet
Output.Position = mul(In.Position,g_mWorldViewProjection);
when I made below change in the vertex shader
Output.Position = In.Position;
I get the static triangle rendered on the screen.
What could be the probable error in my code/technique ?
(
profile: vs_3_0 using D3DXCompileShaderFromFile
)

At the compilation of the pixelshader you overwrite your variable constantTable. So the matrix is only set in the pixelshader and not in the vertexshader. Either you declare an additional variable constantTablePix or set the parameter to NULL if you dont need to pass information to the pixelshader.
The correct order for the matrix is. (I never get the order right, but it works now :) )
D3DXMATRIXA16 matWorldViewProj = matWorld * matView * matProj;

Related

SharpGL and RenderBuffers

I'm attempting to port a pathtracer to GLSL, and to do this I need to modify a shader sample program to use a texture as the framebuffer instead of the backbuffer.
This is the vertex fragment
#version 130
out vec2 texCoord;
// https://rauwendaal.net/2014/06/14/rendering-a-screen-covering-triangle-in-opengl/
void main()
{
float x = -1.0 + float((gl_VertexID & 1) << 2);
float y = -1.0 + float((gl_VertexID & 2) << 1);
texCoord.x = x;
texCoord.y = y;
gl_Position = vec4(x, y, 0, 1);
}
This is the setup code
gl.GenFramebuffersEXT(2, _FrameBuffer);
gl.BindFramebufferEXT(OpenGL.GL_FRAMEBUFFER_EXT, _FrameBuffer[0]);
gl.GenRenderbuffersEXT(2, _RaytracerBuffer);
gl.BindRenderbufferEXT(OpenGL.GL_RENDERBUFFER_EXT, _RaytracerBuffer[0]);
gl.RenderbufferStorageEXT(OpenGL.GL_RENDERBUFFER_EXT, OpenGL.GL_RGBA32F, (int)viewport[2], (int)viewport[3]);
And this is the runtime code
// Get a reference to the raytracer shader.
var shader = shaderRayMarch;
// setup first framebuffer (RGB32F)
gl.BindFramebufferEXT(OpenGL.GL_FRAMEBUFFER_EXT, _FrameBuffer[0]);
gl.Viewport((int)viewport[0], (int)viewport[1], (int)viewport[2], (int)viewport[3]); //0,0,width,height)
gl.FramebufferRenderbufferEXT(OpenGL.GL_FRAMEBUFFER_EXT, OpenGL.GL_COLOR_ATTACHMENT0_EXT, OpenGL.GL_RENDERBUFFER_EXT, _RaytracerBuffer[0]);
gl.FramebufferRenderbufferEXT(OpenGL.GL_FRAMEBUFFER_EXT, OpenGL.GL_DEPTH_ATTACHMENT_EXT, OpenGL.GL_RENDERBUFFER_EXT, 0);
uint [] DrawBuffers = new uint[1];
DrawBuffers[0] = OpenGL.GL_COLOR_ATTACHMENT0_EXT;
gl.DrawBuffers(1, DrawBuffers);
shader.Bind(gl);
shader.SetUniform1(gl, "screenWidth", viewport[2]);
shader.SetUniform1(gl, "screenHeight", viewport[3]);
shader.SetUniform1(gl, "fov", 40.0f);
gl.DrawArrays(OpenGL.GL_TRIANGLES, 0, 3);
shader.Unbind(gl);
int[] pixels = new int[(int)viewport[2]*(int)viewport[3]*4];
gl.GetTexImage(_RaytracerBuffer[0], 0, OpenGL.GL_RGBA32F, OpenGL.GL_INT, pixels);
But when I inspect the pixels coming back from GetTexImage they're black. When I bind this texture in a further transfer shader they remain black. I suspect I'm missing something in the setup code for the renderbuffer and would appreciate any suggestions you have!
Renderbuffers are not textures. So when you do glGetTexImage on your renderbuffer, you probably got an OpenGL error. When you tried to bind it as a texture with glBindTexture, you probably got an OpenGL error.
If you want to render to a texture, you should render to a texture. As in glGenTextures/glTexImage2D/glFramebufferTexture2D.
Also, please stop using EXT_framebuffer_object. You should be using the core FBO feature, which requires no "EXT" suffixes. Not unless you're using a really ancient OpenGL version.

How can I draw surface normals in OpenGL?

I have a vertex format which are all floats, and looks like this:
POSITION POSITION POSITION NORMAL NORMAL NORMAL TEXCOORD TEXCOORD
I was thinking I need to draw lines from the first three floats to the next three floats, then I need to skip the next two floats and continue on. Is there any way of doing this without creating another buffer for each object that's in the correct layout?
I know I can draw just one line per draw call, and just loop over, but that is many draw calls? How is the general way normals are drawn for stuff like debugging?
Also I've thought about indexing, but indexing only helps selecting specific vertices, in this case I want to draw between two attributes of my normal vertex layout.
This cannot be done just by setting appropriate glVertexAttribPointer, since you have to skip the texcoords. Additionally, you don't want to draw a line from position to normal, but from position to position + normal, since normals just describe a direction, not a point in space.
What you can do is to use a geometry shader. Basically, you set up two attributes, one for position, one for normal (as you would do for rendering the model) and issue a draw command with GL_POINTS primitive type. In the geometry shader you then generate a line from position to position + normal.
Normally to draw surface normals you would set up a separate buffer or a geometry shader to do the work. Setting a separate buffer for a mesh to draw just the normals is trivial and doesn't require a draw call for every normal, all of your surface normals would be drawn in a single drawcall
Since you'll be doing it for debugging purposes, there's no need to worry too much about performance and just stick with the quicker method that gets things on screen
The way I'd personally do it depends on whether the mesh has vertex or face normals, we could for instance fill a buffer with a line for each vertex in the mesh whose offset from the vertex itself represent the normal you need to debug with the following pseudocode
var normal_buffer = [];
//tweak to your liking
var normal_length = 10.0;
//this assumes your mesh has 2 arrays of the same length
//containing structs of vertices and normals
for(var i = 0; i < mesh.vertices.length; i++) {
//retrieving the normal associated with this vertex
var nx = mesh.normals[i].x;
var ny = mesh.normals[i].y;
var nz = mesh.normals[i].z;
//retrieving the vertex itself, it'll be the first point of our line
var v1x = mesh.vertices[i].x;
var v1y = mesh.vertices[i].y;
var v1z = mesh.vertices[i].z;
//second point of our line representing the normal direction
var v2x = v1x + nx * normal_length;
var v2y = v1y + ny * normal_length;
var v2z = v1z + nz * normal_length;
buffer.push(v1x, v1y, v1z, v2x, v2y, v2z);
}
You can later on proceed as normal and attach the buffer to a vertex buffer object and use whatever program you like to issue one single draw call that will draw all of your mesh normals
vertbuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertbuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(buffer), gl.STATIC_DRAW);
/* later on in your program */
gl.drawArrays(gl.LINES, 0, buffer.length / 3);
A cool feature of normal debugging is that you can use the normal itself in a fragment shader as an output color to quickly check if it points to the expected direction

Cubemap texturing issue (D3D11, C++)

I have a texture problem with the cubemap I'm rendering and can't seem to figure it out. I've generated a cube map with direct x's texture tools and then read it using
D3DX11CreateShaderResourceViewFromFile(device, L"cubemap.dds", 0, 0, &fullcubemap, 0);
The cubemap texture is not high quality at all and it looks really stretched/distorted. I can definitely tell that the images used for the cubemap match correctly, but it's not great at all at the moment
I'm not sure why this is happening. Is it because my textures are too large/small or is it something else? If it's due to the size of the textures, what is a recommended texture size? I am using a sphere for the cubemap not a cube.
Edit:
Shader:
cbuffer SkyboxConstantBuffer {
float4x4 world;
float4x4 view;
float4x4 projection;
};
TextureCube gCubeMap;
SamplerState samTriLinearSam {
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
struct VertexIn {
float4 position : POSITION;
};
struct VertexOut {
float4 position : SV_POSITION;
float4 spherePosition : POSITION;
};
VertexOut VS(VertexIn vin) {
VertexOut vout = (VertexOut)0;
vin.position.w = 1.0f;
vout.position = mul(vin.position, world);
vout.position = mul(vout.position, view);
vout.position = mul(vout.position, projection);
vout.spherePosition = vin.position;
return vout;
}
float4 PS(VertexOut pin) : SV_Target {
return gCubeMap.Sample(samTriLinearSam, pin.spherePosition);//float4(1.0, 0.5, 0.5, 1.0);
}
RasterizerState NoCull {
CullMode = None;
};
DepthStencilState LessEqualDSS {
DepthFunc = LESS_EQUAL;
};
technique11 SkyTech {
pass p0 {
SetVertexShader(CompileShader(vs_4_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_4_0, PS()));
SetRasterizerState(NoCull);
SetDepthStencilState(LessEqualDSS, 0);
}
}
Draw:
immediateContext->OMSetRenderTargets(1, &renderTarget, nullptr);
XMMATRIX sworld, sview, sprojection;
SkyboxConstantBuffer scb;
sview = XMLoadFloat4x4(&_view);
sprojection = XMLoadFloat4x4(&_projection);
sworld = XMLoadFloat4x4(&_world);
scb.world = sworld;
scb.view = sview;
scb.projection = sprojection;
immediateContext->IASetIndexBuffer(cubeMapSphere->getIndexBuffer(), DXGI_FORMAT_R32_UINT, 0);
ID3D11Buffer* vertexBuffer = cubeMapSphere->getVertexBuffer();
//ID3DX11EffectShaderResourceVariable * cMap;
////cMap = skyboxShader->GetVariableByName("gCubeMap")->AsShaderResource();
immediateContext->PSSetShaderResources(0, 1, &fullcubemap);//textures
//cMap->SetResource(fullcubemap);
immediateContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
immediateContext->VSSetShader(skyboxVertexShader, nullptr, 0);
immediateContext->VSSetConstantBuffers(0, 1, &skyboxConstantBuffer);
immediateContext->PSSetConstantBuffers(0, 1, &skyboxConstantBuffer);
immediateContext->PSSetShader(skyboxPixelShader, nullptr, 0);
immediateContext->UpdateSubresource(skyboxConstantBuffer, 0, nullptr, &scb, 0, 0);
immediateContext->DrawIndexed(cubeMapSphere->getIndexBufferSize(), 0, 0);
Initially I was planning to use this snippet to update the TextureCube variable in the shader
ID3DX11EffectShaderResourceVariable * cMap;
cMap = skyboxShader->GetVariableByName("gCubeMap")->AsShaderResource();
cMap->SetResource(fullcubemap);
But it seems that has no effect, and in fact, without the following line, the sphere I'm using for the cubemap textures with a texture used with another object in the scene, so perhaps there's something going on here? I'm not sure what though.
immediateContext->PSSetShaderResources(0, 1, &fullcubemap);//textures
Edit: Probably not the above, realised that if this wasn't updated, the old texture would be applied as it's never wiped after each draw.
Edit: Tried the cubemap with both a sphere and a cube, still the same texture issue.
Edit: Tried loading the shader resource view differently
D3DX11_IMAGE_LOAD_INFO loadSMInfo;
loadSMInfo.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
ID3D11Texture2D* SMTexture = 0;
hr = D3DX11CreateTextureFromFile(device, L"cubemap.dds",
&loadSMInfo, 0, (ID3D11Resource**)&SMTexture, 0);
D3D11_TEXTURE2D_DESC SMTextureDesc;
SMTexture->GetDesc(&SMTextureDesc);
D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
SMViewDesc.Format = SMTextureDesc.Format;
SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
SMViewDesc.TextureCube.MipLevels = SMTextureDesc.MipLevels;
SMViewDesc.TextureCube.MostDetailedMip = 0;
hr = device->CreateShaderResourceView(SMTexture, &SMViewDesc, &fullcubemap);
Still produces the same output, any ideas?
Edit: Tried increasing the zfar distance and the texture remains the exact same no matter what value I put.
Example with second texture with increased view distance.
This texture is used on another object in my scene and comes out fine.
Edit: I have been trying to mess with the scaling of the texture/object
To achieve this I used
vin.position = vin.position * 50.0f;
This is beginning to look sort of like how it should, however, when I turn my camera angle, the image disappears so I obviously know this isn't correct, but if I could just scale the image per pixel or per vertex properly, I'm sure I could get the end result.
Edit:
I can confirm the cubemap is rendering correctly, I was ignoring the view/projection space and just using world and managed to get this, which is the high quality image i'm after, just not correct. Yes the faces are incorrect, but I'm not fussed about that now, it's easy enough to swap them around, I just need to get it rendering with this quality, in the correct space.
When in camera space does it take into account whether or not it's the outside/inside of the sphere? If my textures were over the outside of the sphere and I have the view from the inside, it's not going to look the same?
Issue is with your texture size, its small, you are applying it on larger surface, Make larger textures with more pixels
Its confirm that zfar and scaling has nothing to do with it.
Finally found the issue, silly mistake.
scb.world = XMMatrixTranspose(sworld);
scb.view = XMMatrixTranspose(sview);
scb.projection = XMMatrixTranspose(sprojection);

WebGL: Particle engine using FBO, how to correctly write and sample particle positions from a texture?

I suspect I'm not correctly rendering particle positions to my FBO, or correctly sampling those positions when rendering, though that may not be the actual problem with my code, admittedly.
I have a complete jsfiddle here: http://jsfiddle.net/p5mdv/53/
A brief overview of the code:
Initialization:
Create an array of random particle positions in x,y,z
Create an array of texture sampling locations (e.g. for 2 particles, first particle at 0,0, next at 0.5,0)
Create a Frame Buffer Object and two particle position textures (one for input, one for output)
Create a full-screen quad (-1,-1 to 1,1)
Particle simulation:
Render a full-screen quad using the particle program (bind frame buffer, set viewport to the dimensions of my particle positions texture, bind input texture, and draw a quad from -1,-1 to 1,1). Input and output textures are swapped each frame.
Particle fragment shader samples the particle texture at the current fragment position (gl_FragCoord.xy), makes some modifications, and writes out the modified position
Particle rendering:
Draw using the vertex buffer of texture sampling locations
Vertex shader uses the sampling location to sample the particle position texture, then transforms them using view projection matrix
Draw the particle using a sprite texture (gl.POINTS)
Questions:
Am I correctly setting the viewport for the FBO in the particle simulation step? I.e. am I correctly rendering a full-screen quad?
// 6 2D corners = 12 vertices
var vertexBuffer = new Float32Array(12);
// -1,-1 to 1,1 screen quad
vertexBuffer[0] = -1;
vertexBuffer[1] = -1;
vertexBuffer[2] = -1;
vertexBuffer[3] = 1;
vertexBuffer[4] = 1;
vertexBuffer[5] = 1;
vertexBuffer[6] = -1;
vertexBuffer[7] = -1;
vertexBuffer[8] = 1;
vertexBuffer[9] = 1;
vertexBuffer[10] = 1;
vertexBuffer[11] = -1;
// Create GL buffers with this data
g.particleSystem.vertexObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, g.particleSystem.vertexObject);
gl.bufferData(gl.ARRAY_BUFFER, vertexBuffer, gl.STATIC_DRAW);
...
gl.viewport(0, 0,
g.particleSystem.particleFBO.width,
g.particleSystem.particleFBO.height);
...
// Set the quad as vertex buffer
gl.bindBuffer(gl.ARRAY_BUFFER, g.screenQuad.vertexObject);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
// Draw!
gl.drawArrays(gl.TRIANGLES, 0, 6);
Am I correctly setting the texture coordinates to sample the particle positions?
for(var i=0; i<numParticles; i++)
{
// Coordinates of particle within texture (normalized)
var texCoordX = Math.floor(i % texSize.width) / texSize.width;
var texCoordY = Math.floor(i / texSize.width) / texSize.height;
particleIndices[ pclIdx ] = texCoordX;
particleIndices[ pclIdx + 1 ] = texCoordY;
particleIndices[ pclIdx + 2 ] = 1; // not used in shader
}
The relevant shaders:
Particle simulation fragment shader:
precision mediump float;
uniform sampler2D mParticleTex;
void main()
{
// Current pixel is the particle's position on the texture
vec2 particleSampleCoords = gl_FragCoord.xy;
vec4 particlePos = texture2D(mParticleTex, particleSampleCoords);
// Move the particle up
particlePos.y += 0.1;
if(particlePos.y > 2.0)
{
// Reset
particlePos.y = -2.0;
}
// Write particle out to texture
gl_FragColor = particlePos;
}
Particle rendering vertex shader:
attribute vec4 vPosition;
uniform mat4 u_modelViewProjMatrix;
uniform sampler2D mParticleTex;
void main()
{
vec2 particleSampleCoords = vPosition.xy;
vec4 particlePos = texture2D(mParticleTex, particleSampleCoords);
gl_Position = u_modelViewProjMatrix * particlePos;
gl_PointSize = 10.0;
}
Let me know if there's a better way to go about debugging this, if nothing else. I'm using webgl-debug to find gl errors and logging what I can to the console.
Your quad is facing away from view so I tried adding gl.disable(gl.CULL_FACE), still no result.
Then I noticed that while resizing window panel with canvas it actually shows one black, square-shaped particle. So it seems that rendering loop is not good.
If you look at console log, it fails to load particle image and it also says that FBO size is 512x1 which is not good.
Some function declarations do not exist, as getTexSize. (?!)
Code needs tiding and grouping, and always check console if you're already using it.
Hope this helps a bit.
Found the problem.
gl_FragCoord is from [0,0] to [screenwidth, screenheight], I was wrongly thinking it was from [0,0] to [1,1].
I had to pass in shader variables for width and height, then normalize the sample coordinates before sampling from the texture.

Updating Textures on Runtime in OpenSceneGraph

I am working on a project in which I am required to capture frames from external device video and render them on openSceneGraph Node. I am also using GLSL shaders. But I don't know how to update textures on runtime. For other uniforms we need to make callbacks but do we also need to make callbacks for samplers in glsl and openSceneGraph ?
My code looks like this. All I am getting right now is a black window.
osg::ref_ptr<osg::Geometry> pictureQuad = osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0f),
osg::Vec3(_deviceNameToImageFrameMap[deviceName].frame->s(),0.0f,0.0f), osg::Vec3(0.0f,0.0f,_deviceNameToImageFrameMap[deviceName].frame->t()),
0.0f, 1.0f,_deviceNameToImageFrameMap[deviceName].frame->s(), _deviceNameToImageFrameMap[deviceName].frame->t());
//creating texture and setting up parameters for video frame
osg::ref_ptr<osg::TextureRectangle> myTex= new osg::TextureRectangle(_deviceNameToImageFrameMap[deviceName].frame.get());
myTex->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
myTex->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
myTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
myTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
_videoSourceNameToNodeMap[sourceName].geode = new osg::Geode();
_videoSourceNameToNodeMap[sourceName].geode->setDataVariance(osg::Object::DYNAMIC);
_videoSourceNameToNodeMap[sourceName].geode->addDrawable(pictureQuad.get());
//apply texture to node
_videoSourceNameToNodeMap[sourceName].geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, myTex.get(), osg::StateAttribute::ON);
_videoSourceNameToNodeMap[sourceName].geode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
_videoSourceNameToNodeMap[sourceName].geode->setDataVariance(osg::Object::DYNAMIC);
//Set uniform sampler
osg::Uniform* srcFrame = new osg::Uniform( osg::Uniform::SAMPLER_2D, "srcFrame" );
srcFrame->set(0);
//Set Uniform Alpha
osg::Uniform* alpha = new osg::Uniform( osg::Uniform::FLOAT, "alpha" );
alpha->set(.5f);
alpha->setUpdateCallback(new ExampleCallback());
//Enable blending
_videoSourceNameToNodeMap[sourceName].geode->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON);
//Adding blend function to node
osg::BlendFunc *bf = new osg::BlendFunc();
bf->setFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
_videoSourceNameToNodeMap[sourceName].geode->getOrCreateStateSet()->setAttributeAndModes(bf);
//apply shader to quad
_videoSourceNameToNodeMap[sourceName].geode->getOrCreateStateSet()->setAttributeAndModes(program, osg::StateAttribute::ON);
//add Uniform to shader
_videoSourceNameToNodeMap[sourceName].geode->getOrCreateStateSet()->addUniform( srcFrame );
_videoSourceNameToNodeMap[sourceName].geode->getOrCreateStateSet()->addUniform( alpha );
Just call image->dirty() and all textures using that image gets updated automatically
You don't need to do this bf->setFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); as this is the default function.