In my project, I draw a house, which consists of wall, floor, mirror, a switch to turn on or turn off the fire system. Everything is going on well by here.
At last, I want to draw a person's reflection on the mirror, but after I add the drawReflection function, things go wrong, scene became a mess. Why? I write the function according to the book.
void House::draw(float timeDelta)
{
_device->SetFVF(d3d::Vertex::FVF);
_device->SetStreamSource(0, _vb, 0, sizeof(d3d::Vertex));
// draw wall
_device->SetMaterial(&d3d::WHITE_MTRL);
_device->SetTexture(0, _wall);
_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 10);
// draw floor
_device->SetMaterial(&d3d::WHITE_MTRL);
_device->SetTexture(0, _floor);
_device->DrawPrimitive(D3DPT_TRIANGLELIST, 30, 2);
// draw mirror
_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
_device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
_device->SetMaterial(&d3d::WHITE_MTRL);
_device->SetTexture(0, _mirror);
_device->DrawPrimitive(D3DPT_TRIANGLELIST, 36, 2);
_device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
// draw switch button
D3DXMATRIX T, Ry, P;
D3DXMatrixTranslation(&T, -4.95f, 2.0f, 3.0f);
D3DXMatrixRotationY(&Ry, D3DX_PI * 1.5f);
P = Ry * T;
_device->SetTransform(D3DTS_WORLD, &P);
_device->SetMaterial(&d3d::BLUE_MTRL);
_device->SetTexture(0, NULL);
_switch->DrawSubset(0);
// draw fire system
D3DXMATRIX I;
D3DXMatrixIdentity(&I);
_device->SetTransform(D3DTS_WORLD, &I);
if(_fSwitchOn)
{
if(_fs->isDead())
_fs->reset();
_fs->update(timeDelta);
_fs->render();
}
// draw reflection of person
//drawReflection();
}
But after I add drawReflection() function to it, it became a mess. Why?
drawReflection() function is below:
void House::drawReflection()
{
// enable stencil
_device->SetRenderState(D3DRS_STENCILENABLE, true);
_device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
_device->SetRenderState(D3DRS_STENCILREF, 0x1);
_device->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);
_device->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
_device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
_device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
_device->SetRenderState(D3DRS_STENCILPASS,
D3DSTENCILOP_REPLACE);
// stop write to target buffer and depth buffer
_device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
_device->SetRenderState(D3DRS_ZWRITEENABLE, false);
// draw the mirror to stencil buffer
_device->SetFVF(d3d::Vertex::FVF);
_device->SetStreamSource(0, _vb, 0, sizeof(d3d::Vertex));
_device->SetMaterial(&d3d::WHITE_MTRL);
_device->SetTexture(0, _mirror);
D3DXMATRIX I;
D3DXMatrixIdentity(&I);
_device->SetTransform(D3DTS_WORLD, &I);
_device->DrawPrimitive(D3DPT_TRIANGLELIST, 36, 2);
_device->SetRenderState(D3DRS_ZWRITEENABLE, true);
// transform the mesh
_device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);
_device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
D3DXMATRIX Reflect, S, T, P;
D3DXPLANE plane(0.0f, 0.0f, 1.0f, -5.0f);
D3DXMatrixReflect(&Reflect, &plane);
// D3DXMatrixScaling(&S, 0.2f, 0.2f, 0.2f);
D3DXVECTOR3 pos;
_person->getPosition(&pos);
D3DXMatrixTranslation(&T, pos.x, pos.y, pos.z);
P = T * Reflect;
_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
_device->SetTransform(D3DTS_WORLD, &P);
_person->draw();
_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
_device->SetRenderState(D3DRS_STENCILENABLE, false);
_device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
}
Related
I have a list of 4 verts loaded into a vert buffer, and an index loaded into a index buffer.
The issue I have is that while the LineList rendermode shows a quad just fine (see below) the TriangleList shows nothing (See below)
void BLX::Model::load(std::filesystem::path path, Model* model, ID3D11Device* d3dDevice, ID3D11DeviceContext* d3dContext)
{
// tmp: just making a quad
float num = 0.5f;
std::vector<BLX::Vertex> vertices = {
BLX::Vertex { DirectX::XMFLOAT3(-num, -num, 0.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 0.5f), }, // 0 = TL
BLX::Vertex { DirectX::XMFLOAT3(num, -num, 0.0f), DirectX::XMFLOAT3(0.0f, 0.5f, 0.0f), }, // 1 = TR
BLX::Vertex { DirectX::XMFLOAT3(num, num, 0.0f), DirectX::XMFLOAT3(0.5f, 0.0f, 0.0f), }, // 2 = BR
BLX::Vertex { DirectX::XMFLOAT3(-num, num, 0.0f), DirectX::XMFLOAT3(0.5f, 0.5f, 0.0f), }, // 3 = BL
};
// line list
//std::vector<unsigned int> indices = { 0, 1, 1, 2, 2, 3, 3, 0 };
// triangle list
std::vector<unsigned int> indices = { 0, 1, 3, 3, 1, 2 };
model->vertexCount = vertices.size();
model->indexCount = indices.size();
// Vertex Buffer
D3D11_BUFFER_DESC vbd = {};
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.Usage = D3D11_USAGE_DEFAULT;
vbd.CPUAccessFlags = 0u;
vbd.MiscFlags = 0u;
vbd.ByteWidth = sizeof(BLX::Vertex) * model->vertexCount;
vbd.StructureByteStride = sizeof(BLX::Vertex);
D3D11_SUBRESOURCE_DATA vsd = {};
vsd.pSysMem = &vertices[0];
vsd.SysMemPitch = 0;
vsd.SysMemSlicePitch = 0;
d3dDevice->CreateBuffer(&vbd, &vsd, &model->vertexBuffer);
/// Index Buffer
D3D11_BUFFER_DESC ibd = {};
ibd.Usage = D3D11_USAGE_DEFAULT;
ibd.ByteWidth = sizeof(unsigned int) * model->indexCount;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA isd = {};
isd.pSysMem = &indices[0];
isd.SysMemPitch = 0;
isd.SysMemSlicePitch = 0;
d3dDevice->CreateBuffer(&ibd, &isd, &model->indexBuffer);
// IA = Input Assembly
// pixel shader
D3DReadFileToBlob(L"PixelShader2.cso", &model->pBlob);
d3dDevice->CreatePixelShader(model->pBlob->GetBufferPointer(), model->pBlob->GetBufferSize(), nullptr, &model->pPixelShader);
// Vertex Shader
D3DReadFileToBlob(L"VertexShader2.cso", &model->pBlob);
d3dDevice->CreateVertexShader(model->pBlob->GetBufferPointer(), model->pBlob->GetBufferSize(), nullptr, &model->pVertexShader);
const D3D11_INPUT_ELEMENT_DESC ied[] =
{
// "Position" correcponds to Vertex Shader Semantic Name
// semantic index
// data type format
// Input slot
// Aligned byte offset
// Input slot class
// Instance data step rate
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
// needs vertex shader blob
d3dDevice->CreateInputLayout(ied, ARRAYSIZE(ied), model->pBlob->GetBufferPointer(), model->pBlob->GetBufferSize(), &model->pInputLayout);
}
void BLX::Model::render(ID3D11Device* d3dDevice, ID3D11DeviceContext* d3dContext, D3D11_VIEWPORT * vp)
{
const UINT stride = sizeof(Vertex);
const UINT offset[] = { 0u, 0u };
d3dContext->IASetVertexBuffers(0u, 1u, vertexBuffer.GetAddressOf(), &stride, &offset[0]);
d3dContext->IASetIndexBuffer(*indexBuffer.GetAddressOf(), DXGI_FORMAT_R32_UINT, offset[1]);
d3dContext->PSSetShader(pPixelShader.Get(), nullptr, 0u);
d3dContext->VSSetShader(pVertexShader.Get(), nullptr, 0u);
d3dContext->IASetInputLayout(pInputLayout.Get());
d3dContext->RSSetViewports(1u, vp);
//d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY::D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
d3dContext->DrawIndexed(indexCount, 0, 0);
}
When using the LineList index and topology:
When using the TriangleList index and topology:
But when I was doing this:
// tmp: just making a quad
float num = 0.5f;
std::vector<BLX::Vertex> vertices = {
BLX::Vertex { DirectX::XMFLOAT3(0.0f, num, 0.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 0.5f), },
BLX::Vertex { DirectX::XMFLOAT3(num, -num, 0.0f), DirectX::XMFLOAT3(0.0f, 0.5f, 0.0f), },
BLX::Vertex { DirectX::XMFLOAT3(-num, -num, 0.0f), DirectX::XMFLOAT3(0.5f, 0.0f, 0.0f), },
};
// triangle list
std::vector<unsigned int> indices = { 0, 1, 2 };
(everything else the exact same) I got this:
Just really curious what I'm not seeing or getting when trying to render two triangles to make up a quad
Your rectangle has indices organized in a clockwise manner, which are culled by the default rasterizer (since you do not specify one it culls clockwise primitives)
Your triangle vertices order was counter clockwise, so the primitive was not culled.
To solve it, two solutions:
Change your indices order :
std::vector<unsigned int> indices = { 0, 3, 1, 3, 2, 1 };
Disable culling in the rasterizer state :
First create one Rasterizer Description
D3D11_RASTERIZER_DESC raster_desc;
raster_desc.FillMode = D3D11_FILL_SOLID;
raster_desc.CullMode= D3D11_CULL_NONE;
raster_desc.FrontCounterClockwise = false;
raster_desc.DepthBias = 0;
raster_desc.DepthBiasClamp= 0.0f;
raster_desc.SlopeScaledDepthBias= 0.0f;
raster_desc.DepthClipEnable= true;
raster_desc.ScissorEnable= false;
raster_desc.MultisampleEnable= false;
raster_desc.AntialiasedLineEnable= false;
Then create a rasterizer state using your device:
ID3D11RasterizerState* raster_state;
HRESULT hr =d3dDevice->CreateRasterizerState(&raster_desc, &raster_state);
Before the draw, assign your rasterizer state to your context:
d3dContext->RSSetState(raster_state);
Your two meshes, triangle and quad, have opposite triangle winding order. Here’s how.
By default, D3D11 uses CullMode=Back and FrontCounterClockwise=FALSE.
This means it only renders front faces, and front face is defined as “when the vertices are counter-clockwise”.
As you see from the above illustration, your triangle indeed has counter-clockwise order, however both triangles of your quad are clockwise, GPU considers them as back faces and skips both.
You have many ways to fix, any of the following will do.
Reorder vertices in vertex buffer.
Flip triangles in index buffer to { 0, 3, 1, 1, 3, 2 }
Change rasterizer state to disable back face culling, CullMode=D3D11_CULL_NONE
Change rasterizer state to switch front face winding direction, FrontCounterClockwise=TRUE
Change matrix passed to vertex shader to include mirroring component, e.g. scale with vector [ -1, 1, 1 ] represents a mirror transform that flips X, this will flip winding order of the whole mesh.
I needed to draw some simple shapes and I decided to go with D3D9. After going through a few of the tutorials on directxtutorial.com, I finally have all the code and knowledge I need to make my first shape appear on the screen. The problem is, though, that no image is appearing. I've looked over the code many times and have compared it with the code on the website, and it all checks out. Why is nothing rendering on the screen?
#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;
LPDIRECT3DVERTEXBUFFER9 vbuffer;
struct CUSTOMVERTEX
{
float x, y, z, rhw;
DWORD color;
};
void InitD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = true;
d3dpp.hDeviceWindow = hWnd;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
}
void InitGraphics()
{
CUSTOMVERTEX verticies[]
{
{50, 70, 1.0f, 1.0f, D3DCOLOR_XRGB(250, 0, 0),},
{70, 50, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 250, 0),},
{40, 80, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 250),},
};
d3ddev->CreateVertexBuffer(3 * sizeof(CUSTOMVERTEX), NULL, CUSTOMFVF, D3DPOOL_MANAGED, &vbuffer, NULL);
void* vp;
vbuffer->Lock(0, 0, (void**)&vp, NULL);
memcpy(vp, verticies, sizeof(verticies));
vbuffer->Unlock();
}
void Draw()
{
d3ddev->Clear(NULL, NULL, D3DCLEAR_TARGET, NULL, 1.0f, NULL);
d3ddev->BeginScene();
d3ddev->SetFVF(CUSTOMFVF);
d3ddev->SetStreamSource(0, vbuffer, 0, sizeof(CUSTOMVERTEX));
d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
void ReleaseD3D()
{
d3d->Release();
d3ddev->Release();
vbuffer->Release();
}
Turns out my vertex positions weren't triangle enough to make a triangle. Thanks for the help, though, it reminded me to set up error-checking.
I started from an example WebGL program that shows a single cube on the page. The example code does not use classes.
I want to be able to draw multiple cubes that can move independently. So I added a "Cube" class. Each instance of this class uses its own "program". I create two objects, but I draw only the first one. Unfortunately the later instantiated object is shown instead. E.g. in the code below "ground" is shown instead of "cube1".
Relevant parts of the code is below. Can you see any problem with it? How can I fix it?
...
////
class Cube {
constructor(gl, color) {
this.gl = gl;
this.program = initShaders(gl, "vertex-shader", "fragment-shader");
//// Model buffers and attributes
[this.pointsArray, this.colorsArray] = cubePointsAndColors(color);
this.numVertices = 36;
this.initAttributeBuffers();
//// Camera Related Uniforms Matrices
this.modelViewMatrixLoc = gl.getUniformLocation(
this.program,
"modelViewMatrix"
);
this.projectionMatrixLoc = gl.getUniformLocation(
this.program,
"projectionMatrix"
);
}
draw() {
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.numVertices);
}
initAttributeBuffers() {
// arrange cube color data stuff
var cBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, cBuffer);
this.gl.bufferData(
this.gl.ARRAY_BUFFER,
flatten(this.colorsArray),
this.gl.STATIC_DRAW
);
var vColor = this.gl.getAttribLocation(this.program, "vColor");
this.gl.vertexAttribPointer(vColor, 4, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(vColor);
// arrange cube vertex data stuff
var vBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vBuffer);
this.gl.bufferData(
this.gl.ARRAY_BUFFER,
flatten(this.pointsArray),
this.gl.STATIC_DRAW
);
var vPosition = this.gl.getAttribLocation(this.program, "vPosition");
this.gl.vertexAttribPointer(vPosition, 4, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(vPosition);
}
}
window.onload = function init() {
//// initialize WebGl System
const canvas = document.getElementById("gl-canvas");
const gl = WebGLUtils.setupWebGL(canvas);
if (!gl) {
alert("WebGL isn't available");
}
gl.viewport(0, 0, canvas.width, canvas.height);
aspect = canvas.width / canvas.height;
gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.enable(gl.DEPTH_TEST);
//// Initialize game objects
var cube1 = new Cube(gl, vec4(1.0, 0.0, 0.0, 1.0));
var ground = new Cube(gl, vec4(0.0, 1.0, 0.0, 1.0));
let gameObjects = [cube1];
// sliders for viewing parameters
readGUI();
render(gl, gameObjects);
};
////
var render = function(gl, gameObjects) {
//// clear the background
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//// camera settings
eye = vec3(
radius * Math.sin(theta) * Math.cos(phi),
radius * Math.sin(theta) * Math.sin(phi),
radius * Math.cos(theta)
);
modelViewMatrix = lookAt(eye, at, up);
projectionMatrix = perspective(fovy, aspect, near, far);
//// draw all objects
for (let objectI = 0; objectI < gameObjects.length; objectI++) {
const gameObject = gameObjects[objectI];
gl.useProgram(gameObject.program);
gl.uniformMatrix4fv(
gameObject.modelViewMatrixLoc,
false,
flatten(modelViewMatrix)
);
gl.uniformMatrix4fv(
gameObject.projectionMatrixLoc,
false,
flatten(projectionMatrix)
);
gameObject.draw();
}
requestAnimFrame(() => render(gl, gameObjects));
};
...
In WebGL 1.0 drawArrays, uses the vertices which are currently specified by vertexAttribPointer and enabled by enableVertexAttribArray.
Use properties to store the buffer objects (this.cBuffer, this.vBuffer) and attribute indices (this.vColor, this.vPosition):
initAttributeBuffers() {
// arrange cube color data stuff
this.cBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cBuffer);
this.gl.bufferData(
this.gl.ARRAY_BUFFER,
flatten(this.colorsArray),
this.gl.STATIC_DRAW
);
this.vColor = this.gl.getAttribLocation(this.program, "vColor");
// arrange cube vertex data stuff
this.vBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vBuffer);
this.gl.bufferData(
this.gl.ARRAY_BUFFER,
flatten(this.pointsArray),
this.gl.STATIC_DRAW
);
this.vPosition = this.gl.getAttribLocation(this.program, "vPosition");
}
Specify and enable the arrays of generic vertex attribute data right before the draw call:
draw() {
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cBuffer);
this.gl.vertexAttribPointer(this.vColor, 4, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(this.vColor);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vBuffer);
this.gl.vertexAttribPointer(this.vPosition, 4, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(this.vPosition);
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.numVertices);
}
In WebGL 2.0 (or by the use of the extension OES_vertex_array_object), that can be simplified by the use of WebGLVertexArrayObjects.
The vertex specification is stated in the vertex array object:
initAttributeBuffers() {
// create vertex array object
this.vao = this.gl.createVertexArray();
this.gl.bindVertexArray(this.vao);
// arrange cube color data stuff
var cBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, cBuffer);
this.gl.bufferData(
this.gl.ARRAY_BUFFER,
flatten(this.colorsArray),
this.gl.STATIC_DRAW
);
var vColor = this.gl.getAttribLocation(this.program, "vColor");
this.gl.vertexAttribPointer(vColor, 4, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(vColor);
// arrange cube vertex data stuff
var vBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vBuffer);
this.gl.bufferData(
this.gl.ARRAY_BUFFER,
flatten(this.pointsArray),
this.gl.STATIC_DRAW
);
var vPosition = this.gl.getAttribLocation(this.program, "vPosition");
this.gl.vertexAttribPointer(vPosition, 4, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(vPosition);
}
It is sufficient to bind the vertex array before the draw call:
draw() {
this.gl.bindVertexArray(this.vao);
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.numVertices);
}
I am trying to draw two hollow circles that are surrounding a cube which is located at the 0, 0, 0 position..
so far I've implemented the cube and the two circles here is what I get.
there are two strange things happening here.
One is that I want to draw the circles but I can see the lines radiating from the origin.
and two is that interpolated colors, even though I set just one color for the fragment shader.
here is you can see clearly those lines with interpolated color...
here is my vertex shader code and the fragment shader code
"use strict";
const loc_aPosition = 1;
const loc_aColor = 2;
const loc_UVCoord = 3;
const VSHADER_SOURCE =
`#version 300 es
layout(location=${loc_aPosition}) in vec4 aPosition;
layout(location=${loc_aColor}) in vec4 aColor;
layout(location=${loc_UVCoord}) in vec2 UVCoord;
out vec4 vColor;
out vec2 vUVCoord;
uniform mat4 uMVP;
void main()
{
gl_Position = uMVP * aPosition;
vColor = aColor;
vUVCoord = UVCoord;
}`;
const FSHADER_SOURCE =
`#version 300 es
precision mediump float;
in vec4 vColor;
out vec4 fColor;
void main()
{
fColor = vColor;
}`;
and the initilize functions for the two circles and there is the only difference is the target plane.
function init_equator(gl)
{
let vertices = []; // for the vertices
let color = [1, 0, 0]; // red color
for(var i = 0; i <= 360; i+=10)
{
let j = i * Math.PI/180;
let vert = [R * Math.cos(j), 0, R * Math.sin(j)]; // drawing a circle at the XZ plane since it has to be an equator for the cube...
vertices.push( vert[0], vert[1], vert[2] ); // push the vertices
vertices.push( color[0], color[1], color[2]); // set the color
}
const SZ = vertices.BYTES_PER_ELEMENT;
let vao = gl.createVertexArray();
gl.bindVertexArray(vao);
let vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(loc_aPosition, 3, gl.FLOAT, false, SZ * 6, 0); // stride is 6, 3 for positions and 3 for the color
gl.enableVertexAttribArray(loc_aPosition);
gl.vertexAttribPointer(loc_aColor, 3, gl.FLOAT, false, SZ * 6, SZ * 3); // stride is 6, offset is this is because 3 color elements are located after 3 position elements..
gl.enableVertexAttribArray(loc_aColor);
gl.bindVertexArray(null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
return { vao, n : vertices.length / 3 }; // since it has three coordinates so devide by 3
}
function init_latitude(gl)
{
let vertices = []; // for the vertices
let color = [1, 0, 0]; // supposed to be the red
for(var i = 0; i <= 360; i+=10)
{
let j = i * Math.PI/180;
let vert = [0, R * Math.cos(j), R * Math.sin(j)]; // drawing a circle on the YZ plane
vertices.push( vert[0], vert[1], vert[2] );
vertices.push( color[0], color[1], color[2]);
}
const SZ = vertices.BYTES_PER_ELEMENT;
let vao = gl.createVertexArray();
gl.bindVertexArray(vao);
let vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(loc_aPosition, 3, gl.FLOAT, false, SZ * 6, 0); // stride is 6, 3 for positions and 3 for the color
gl.enableVertexAttribArray(loc_aPosition);
gl.vertexAttribPointer(loc_aColor, 3, gl.FLOAT, false, SZ * 6, SZ * 3); // stride is 6, offset is this is because 3 color elements are located after 3 position elements..
gl.enableVertexAttribArray(loc_aColor);
gl.bindVertexArray(null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
return { vao, n : vertices.length / 3 }; // since it has three coordinates so devide by 3
}
I refer these drawing fucntions from here drawing circle
in the main function I called the draw function like this..
........
MVP.setOrtho(LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR); // setting MVP matrix to orthographic mode
MVP.lookAt(FIXED_X, FIXED_Y, FIXED_Z, 0,0,0, 0,1,0); // Eye position x, y, z Look at position 0, 0, 0 Up vector 0, 1, 0
gl.uniformMatrix4fv(loc_MVP, false, MVP.elements);
gl.bindVertexArray(cube.vao);
gl.drawElements(gl.TRIANGLES, cube.n, gl.UNSIGNED_BYTE, 0)
gl.bindVertexArray(null);
gl.bindVertexArray(equator.vao);
gl.drawArrays(gl.LINE_LOOP, 0, equator.n);
gl.bindVertexArray(null);
gl.bindVertexArray(latitudeCircle.vao);
gl.drawArrays(gl.LINE_LOOP, 0, latitudeCircle.n);
gl.bindVertexArray(null);
I have no ideas why the lines are radiating from the origin and the mixed color...
could somebody help me?
this line, which appears twice in the code you posted
const SZ = vertices.BYTES_PER_ELEMENT;
is SZ will be undefined. vertices is a native JavaScript array, not a typedarray array like Float32Array. After that every calculation with SZ will be 0 or NaN
In other words these lines
gl.vertexAttribPointer(loc_aPosition, 3, gl.FLOAT, false, SZ * 6, 0);
gl.vertexAttribPointer(loc_aColor, 3, gl.FLOAT, false, SZ * 6, SZ * 3);
Will be
gl.vertexAttribPointer(loc_aPosition, 3, gl.FLOAT, false, 0, 0);
gl.vertexAttribPointer(loc_aColor, 3, gl.FLOAT, false, 0, 0);
Which means every other position is a color, and every other color is a position which explains why lines go to the center and why colors are interpolated.
Note that if you had stepped through the code in the debugger you'd have probably seen this issue so it would be good to learn how to use the debugger.
Also FYI unrelated to your issue you don't need to call gl.bindVertexArray twice in a row, once with null and once with the next thing you want to draw with.
this
gl.bindVertexArray(cube.vao);
gl.drawElements(gl.TRIANGLES, cube.n, gl.UNSIGNED_BYTE, 0)
gl.bindVertexArray(null);
gl.bindVertexArray(equator.vao);
gl.drawArrays(gl.LINE_LOOP, 0, equator.n);
gl.bindVertexArray(null);
gl.bindVertexArray(latitudeCircle.vao);
gl.drawArrays(gl.LINE_LOOP, 0, latitudeCircle.n);
gl.bindVertexArray(null);
can just be this
gl.bindVertexArray(cube.vao);
gl.drawElements(gl.TRIANGLES, cube.n, gl.UNSIGNED_BYTE, 0)
gl.bindVertexArray(equator.vao);
gl.drawArrays(gl.LINE_LOOP, 0, equator.n);
gl.bindVertexArray(latitudeCircle.vao);
gl.drawArrays(gl.LINE_LOOP, 0, latitudeCircle.n);
gl.bindVertexArray(null); // this is also not technically needed
Also also, you can use the spread operator.
This
vertices.push( vert[0], vert[1], vert[2] ); // push the vertices
vertices.push( color[0], color[1], color[2]); // set the color
can be this
vertices.push( ...vert ); // push the vertices
vertices.push( ...color ); // set the color
Also you might find these tutorials useful.
I am trying to build a simple 2D game using 2D sprites with DirectX 9, and I'm having problems getting the images to come out cleanly. I'd like to load bmp images and display them on the screen as is (no interpolation, no magnification, no filtering or anti-aliasing, etc).
I'm sure I'm missing something, but when I try and render a 100x100 bmp to the screen, it looks choppy and distorted, like a pixel art image would normally look when shrunken slightly. I want the bmp to look exactly as it does when loaded in MS Paint.
Does anyone have any idea why this might be the case? My code is shown below:
Initialization code:
g_DxCom = Direct3DCreate9( D3D_SDK_VERSION );
if ( g_DxCom == NULL )
{
return false;
}
D3DDISPLAYMODE d3dDisplayMode;
if ( FAILED( g_DxCom->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3dDisplayMode ) ) )
{
return false;
}
D3DPRESENT_PARAMETERS d3dPresentParameters;
::ZeroMemory( &d3dPresentParameters, sizeof(D3DPRESENT_PARAMETERS) );
d3dPresentParameters.Windowed = FALSE;
d3dPresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dPresentParameters.BackBufferFormat = d3dDisplayMode.Format; // D3DFMT_X8R8G8B8
d3dPresentParameters.BackBufferWidth = d3dDisplayMode.Width;
d3dPresentParameters.BackBufferHeight = d3dDisplayMode.Height;
d3dPresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
if ( FAILED( g_DxCom->CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
this->hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dPresentParameters,
&pd3dDevice ) ) )
{
if ( FAILED( g_DxCom->CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
this->hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dPresentParameters,
&pd3dDevice ) ) )
{
return false;
}
}
texture = NULL;
bg_texture = NULL;
Render code:
LPDIRECT3DDEVICE9 g_dxDevice;
float float1 = 99.5f; // I'd like to render my 100x100 sprite from screen coordinates 100, 100 to 200, 200
float float2 = 198.5f;
CUSTOMVERTEX OurVertices[] =
{
{ float1, float2, 1.0f, 1.0f, 0.0f, 1.0f },
{ float1, float1, 1.0f, 1.0f, 0.0f, 0.0f },
{ float2, float1, 1.0f, 1.0f, 1.0f, 0.0f },
{ float1, float2, 1.0f, 1.0f, 0.0f, 1.0f },
{ float2, float1, 1.0f, 1.0f, 1.0f, 0.0f },
{ float2, float2, 1.0f, 1.0f, 1.0f, 1.0f }
};
LPDIRECT3DVERTEXBUFFER9 v_buffer;
g_dxDevice->CreateVertexBuffer( 6 * sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL );
VOID* pVoid;
// Lock the vertex buffer into memory
v_buffer->Lock( 0, 0, &pVoid, 0 );
// Copy our vertex buffer to memory
::memcpy( pVoid, OurVertices, sizeof(OurVertices) );
// Unlock buffer
v_buffer->Unlock();
LPDIRECT3DTEXTURE9 g_texture;
HRESULT hError;
DWORD dwTextureFilter = D3DTEXF_NONE;
g_dxDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, dwTextureFilter );
g_dxDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, dwTextureFilter );
g_dxDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, dwTextureFilter );
g_dxDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
g_dxDevice->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
g_dxDevice->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
hError = D3DXCreateTextureFromFile( g_dxDevice, L"Test.bmp", &g_texture ); // 100x100 sprite
g_dxDevice->SetTexture( 0, g_texture );
g_dxDevice->Clear( 0,
NULL,
D3DCLEAR_TARGET,
D3DCOLOR_XRGB( 0, 40, 100 ),
1.0f,
0 );
g_dxDevice->BeginScene();
// Do rendering on the back buffer here
g_dxDevice->SetFVF( CUSTOMFVF );
g_dxDevice->SetStreamSource( 0, v_buffer, 0, sizeof(CUSTOMVERTEX) );
g_dxDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 6 );
g_dxDevice->EndScene();
g_dxDevice->Present( NULL, NULL, NULL, NULL );
g_texture->Release();
v_buffer->Release();
Okay, so I've finally figured it out, and I should have known this was the case.
It looks like DirectX9 only works with textures with sizes that are multiples of 2. If I change the texture so that the sprite square is 128 x 128 (just adding some transparency) and run the application with float2 changed appropriately, there is no distortion in the rendered image.
Hurrah...