I have a bitmap that I want to draw zoomed in and with straight, defined edges between pixels.
I have tried setting the MAG filter to NEAREST:
gl.bindTexture(gl.TEXTURE_2D,this.tex);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);
...
gl.drawArrays(gl.TRIANGLES,0,6); // draw the texture
However, when I draw it the pixels bleed together:
This is webGL so I have shaders. My shader code is super-simple:
Vertex shader:
...
attribute vec2 texCoord;
varying vec2 texel;
void main() {
texel = texCoord;
...
And fragment shader:
...
varying vec2 texel;
uniform sampler2D texture;
void main() {
vec4 fragColour = texture2D(texture,texel);
...
Here's a larger snippet of the relative code:
map = {
vbo: gl.createBuffer(),
tex: gl.createTexture(),
program: createProgram(
"precision mediump float;\n"+
"uniform mat4 mvMatrix, pMatrix;\n"+
"attribute vec3 vertex;\n"+
"attribute vec2 texCoord;\n"+
"varying vec2 texel;\n"+
"void main() {\n"+
" texel = texCoord;\n"+
" gl_Position = pMatrix * mvMatrix * vec4(vertex,1.0);\n"+
"}\n",
"precision mediump float;\n"+
"uniform vec4 colour;\n"+
"uniform float fogDensity;\n"+
"uniform vec4 fogColour;\n"+
"varying vec2 texel;\n"+
"uniform sampler2D texture;\n"+
"const float LOG2 = 1.442695;\n"+
"void main() {\n"+
" float z = gl_FragCoord.z / gl_FragCoord.w;\n"+
" float fogFactor = exp2(-fogDensity*fogDensity*z*z*LOG2);\n"+
" fogFactor = clamp(fogFactor,0.0,1.0);\n"+
" vec4 fragColour = texture2D(texture,texel) * colour;\n"+
" gl_FragColor = mix(fogColour,fragColour,fogFactor);\n"+
"}\n",
["mvMatrix","pMatrix","colour","fogDensity","fogColour","texture"],
["vertex","texCoord"]),
plane: [[0,0,0],[0,1,0]],
init: function(w,h) {
this.w = w;
this.h = h;
var vertices = [
w,0,0, 1,0,
0,0,0, 0,0,
w,0,h, 1,1,
w,0,h, 1,1,
0,0,0, 0,0,
0,0,h, 0,1,
];
gl.bindBuffer(gl.ARRAY_BUFFER,this.vbo);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(vertices),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER,null);
this._mapArrayBuffer = new ArrayBuffer(w*h*4);
this._mapByteBuffer = new Uint8Array(this._mapArrayBuffer);
this.map = new Uint32Array(this._mapArrayBuffer);
for(var i=0; i<w*h; i++) // test data: red and green pixels
this.map[i] = Math.random()>0.5? 0xff000080: 0xff008000;
createTexture(this.tex,w,h,this._mapByteBuffer,true);
},
draw: function() {
var program = this.program;
gl.useProgram(program);
gl.uniformMatrix4fv(program.pMatrix,false,camera.pMatrix);
gl.uniformMatrix4fv(program.mvMatrix,false,camera.mvMatrix);
gl.uniform4f(program.colour,1,1,1,1);
gl.uniform4f(program.fogColour,1,1,1,1);
gl.uniform1f(program.fogDensity,0.03);
gl.bindTexture(gl.TEXTURE_2D,this.tex);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);
gl.bindBuffer(gl.ARRAY_BUFFER,this.vbo);
gl.enableVertexAttribArray(program.vertex);
gl.vertexAttribPointer(program.vertex,3,gl.FLOAT,false,5*4,0);
gl.enableVertexAttribArray(program.texCoord);
gl.vertexAttribPointer(program.texCoord,2,gl.FLOAT,false,5*4,3*4);
gl.drawArrays(gl.TRIANGLES,0,6);
gl.disableVertexAttribArray(program.texCoord);
gl.disableVertexAttribArray(program.vertex);
gl.bindBuffer(gl.ARRAY_BUFFER,null);
gl.bindTexture(gl.TEXTURE_2D,null);
gl.useProgram(null);
},
};
function createTexture(tex,width,height,data,noMipMap) {
tex = tex || gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D,tex);
tex.width = width || data.width;
tex.height = height || data.height;
if(width != null)
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,data || null);
else
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,data);
if(anisotropy)
gl.texParameterf(gl.TEXTURE_2D,anisotropic.TEXTURE_MAX_ANISOTROPY_EXT,anisotropy);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);
if(!noMipMap && !(tex.width&(tex.width-1)) && !(tex.height&(tex.height-1))) { //pow2
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_LINEAR);
gl.generateMipmap(gl.TEXTURE_2D);
} else
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D,null);
_textures.push(tex);
return tex;
}
[SOLVED] The problem was that I was enabling anisotropy for the texture. Anisotropy trumps gl_NEAREST, it seems. If you want to use gl_NEAREST on a texture, its important to not also have anisotropy set.
Related
Basically I've created a plane and rotate it 5 times to be a cube. I made cube with different colors of each side. And did some rotation with touch event.
Everthing was good so far, but the cube turned out to be like this.
Please help it's been driving me crazy!
My cube code:
public class PhotoCube{
public ArrayList<FloatBuffer> vertexBufferList = new ArrayList<>();
public int[][] lists = {
{0,1,0,0}, //front
{1,0,0,-90}, //top
{0,1,0,-90}, //left
{0,1,0,90}, //
{1,0,0,90}, //bottom
{0,1,0,180} //right
};
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static final float[] coords = { // in counterclockwise order:
0.5f, 0.5f, 0.5f, // top right
-0.5f, 0.5f, 0.5f, // top left
-0.5f, -0.5f, 0.5f, // bottom left
0.5f, -0.5f, 0.5f // bottom right
};
static final float[][] colorList = {
{1f,0f,0f,1f},
{0f,1f,0f,1f},
{1f,1f,1f,1f},
{1f,1f,0f,1f},
{1f,0f,1f,1f},
{0f,1f,1f,1f}
};
public PhotoCube() {
final int maxVertices = 6;
for(int[] list:lists){
float[] currentCoords = coords.clone();
for(int i=0;i<12;i+=3){
float x = coords[i];
float y = coords[i+1];
float z = coords[i+2];
double angle = Math.toRadians(list[3]);
currentCoords[i]=(float) ((list[0]==1)?x:(list[1]==1)?x*Math.cos(angle)+z*Math.sin(angle):x*Math.cos(angle)-y*Math.sin(angle));
currentCoords[i+1]=(float) ((list[0]==1)?y*Math.cos(angle)-z*Math.sin(angle):(list[1]==1)?y:x*Math.sin(angle)+y*Math.cos(angle));
currentCoords[i+2]=(float) ((list[0]==1)?z*Math.cos(angle)+y*Math.sin(angle):(list[1]==1)?z*Math.cos(angle)-x*Math.sin(angle):z);
}
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
currentCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
FloatBuffer vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(currentCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
if(vertexBufferList.size()==maxVertices){
vertexBufferList.remove(0);
}
vertexBufferList.add(vertexBuffer);
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
createProgram();
GLES20.glLinkProgram(mProgram);
// creates OpenGL ES program executables
}
}
public void createProgram(){
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
}
public void draw(int order) {
final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
int positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(positionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, true,
vertexStride, vertexBufferList.get(order));
// get handle to fragment shader's vColor member
int colorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(colorHandle, 1, colorList[order], 0);
GLES20.glDrawElements(
GLES20.GL_TRIANGLES,
drawOrder.length,
GL_UNSIGNED_SHORT,
drawListBuffer);
// Disable vertex array
//GLES20.glDisableVertexAttribArray(positionHandle);
}
}
My Renderer code:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private PhotoCube mPhotoCube;
public final float[] vPMatrix = new float[16];
private final float[] projectionMatrix = new float[16];
private final float[] viewMatrix = new float[16];
private int vPMatrixHandle = -1;
private volatile float mAngleX = 0;
private volatile float mAngleY = 0;
private float[] rotationMX = new float[16];
private float[] rotationMY = new float[16];
private float[] scratch = new float[16];
public MyGLRenderer(Context context){
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
mPhotoCube = new PhotoCube();
vPMatrixHandle = GLES20.glGetUniformLocation(mPhotoCube.mProgram, "uVPMatrix");
onDrawFrame(unused);
}
public void onDrawFrame(GL10 unused) {
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFuncSeparate(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA, GLES20.GL_ZERO, GLES20.GL_ONE);
Matrix.setRotateM(rotationMX, 0, -mAngleX, 0, 1, 0);
Matrix.setLookAtM(viewMatrix, 0, 0, 0, 5, 0f, 0f, -5f, 0f, 1.0f, 0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
Matrix.multiplyMM(scratch, 0, vPMatrix, 0, rotationMX, 0);
Matrix.setRotateM(rotationMY, 0, -mAngleY, scratch[0], scratch[4], scratch[8]);
Matrix.multiplyMM(scratch, 0, scratch, 0, rotationMY, 0);
vPMatrixHandle = GLES20.glGetUniformLocation(mPhotoCube.mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, scratch, 0);
for(int i=0;i<mPhotoCube.lists.length;i++){
mPhotoCube.draw(i);
}
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
}
Here's my shader code
final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
Thank you in advance.
You have to enable the Depth Test Depth test ensures that fragments that lie behind other fragments are discarded:
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
When you enable the depth test you must also clear the depth buffer:
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
However, if you have transparent objects and want to use Blending, the depth test must be disabled and you must draw the triangles of the meshes in sorted order from back to front. Also see OpenGL depth sorting
I have the .dds cube map texture loaded it in and put it on the sphere model. Obviously it doesn't look right, because I would have to map the texture to the right points on the sphere.
how can I map the texture to the right points on the sphere?
somethings like that:
TextureCube TEXTURE_REFLECTION;
//...
VS_OUTPUT vs(VS_INPUT IN) {
//...
float4 worldPosition = mul(float4(IN.Position.xyz, 1.0f), IN.World);
OUT.worldpos = worldPosition.xyz;
//...
}
PS_OUTPUT ps(VS_OUTPUT IN) {
//...
float4 ColorTex = TEXTURE_DIFFUSE.Sample(SAMPLER_DEFAULT, IN.TexCoord);
float3 normalFromMap = mul(2.0f * TEXTURE_NORMAL.Sample(SAMPLER_DEFAULT, IN.TexCoord).xyz - 1.0f), IN.tangentToWorld);
//...
float3 incident = -normalize(CAMERA_POSITION - IN.worldpos);
float3 reflectionVector = reflect(incident, normalFromMap);
ColorTex.rgb = lerp(ColorTex.rgb, TEXTURE_REFLECTION.Sample(SAMPLER_DEFAULT, reflectionVector).rgb, MATERIAL_REFLECTIVITY);
}
I figured it out.
Pixel shader:
TextureCube CubeMap: register(t0);
SamplerState TexSampler : register(s0);
float4 main(LightingPixelShaderInput input) : SV_Target
{
float4 cubeTexture = CubeMap.Sample(TexSampler, input.worldNormal);
//light calculations
float3 finalColour = (gAmbientColour + diffuseLights) * cubeTexture.rgb +
(specularLights) * cubeTexture.a;
return float4(finalColour, 1.0f);
}
For an experiment I want to pass all edges of a triangle to the pixel shader and manually calculate the pixel position with the triangle edges and bayrcentric coodinates.
In order to do this I wrote a geometry shader that passes all edges of my triangle to the pixel shader:
struct GeoIn
{
float4 projPos : SV_POSITION;
float3 position : POSITION;
};
struct GeoOut
{
float4 projPos : SV_POSITION;
float3 position : POSITION;
float3 p[3] : TRIPOS;
};
[maxvertexcount(3)]
void main(triangle GeoIn i[3], inout TriangleStream<GeoOut> OutputStream)
{
GeoOut o;
// add triangle data
for(uint idx = 0; idx < 3; ++idx)
{
o.p[idx] = i[idx].position;
}
// generate verices
for(idx = 0; idx < 3; ++idx)
{
o.projPos = i[idx].projPos;
o.position = i[idx].position;
OutputStream.Append(o);
}
OutputStream.RestartStrip();
}
The pixel shader outputs the manually reconstructed position:
struct PixelIn
{
float4 projPos : SV_POSITION;
float3 position : POSITION;
float3 p[3] : TRIPOS;
float3 bayr : SV_Barycentrics;
};
float4 main(PixelIn i) : SV_TARGET
{
float3 pos = i.bayr.x * i.p[0] + i.bayr.y * i.p[1] + i.bayr.z * i.p[2];
return float4(abs(pos), 1.0);
}
And I get the following (expected) result:
However, when I modify my PixelIn struct by adding nointerpolation to p[3]:
struct PixelIn
{
...
nointerpolation float3 p[3] : TRIPOS;
};
I get:
I did not expect a different result because I am not changing the values of p[] for a single triangle in the geometry shader. I tried debugging it by changing the output to float4(abs(i.p[0]), 1.0); with and without interpolation. Without nointerpolation the values of p[] do not vary within a triangle (which makes sense, because all should have the same value). With nointerpolation the values of p[] do change slightly. Why is that the case? I thought nointerpolate was not supposed to interpolate anything.
Edit:
This is the wireframe of my geometry:
So I am trying to create circles using the midpoint algorithm. I'm having trouble on how to handle buffers and basically get WebGL properly set up. Using the console I can see that the algorithm is working fine and making the vertex arrray, but I need help understanding what to do with the use.Program, createBuffers, drawArrays. Where should I place them?
Also, should I concat the circle everytime I call it in the START() function?
like: circle(blah blah).concat(circle(blah blah));
var vertexShaderText =
[
'precision mediump float;',
'',
'attribute vec2 vertPosition;',
'attribute vec3 vertColor;',
'varying vec3 fragColor;',
'',
'void main()',
'{',
' fragColor = vertColor;',
' gl_Position = vec4(vertPosition, 0.0, 1.0);',
'}'
].join('\n');
var fragmentShaderText =
[
'precision mediump float;',
'',
'varying vec3 fragColor;',
'void main()',
'{',
' gl_FragColor = vec4(fragColor, 1.0);',
'}'
].join('\n');
var START = function () {
console.log('This is working');
var canvas = document.getElementById('sky');
var gl = canvas.getContext('webgl');
if (!gl) {
console.log('WebGL not supported, falling back on experimental-webgl');
gl = canvas.getContext('experimental-webgl');
}
if (!gl) {
alert('Your browser does not support WebGL');
}
gl.clearColor(.3, .3, .7, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Create shaders
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader =
gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader, vertexShaderText);
gl.shaderSource(fragmentShader, fragmentShaderText);
//create a program for the shaders
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
var circle = function (xmid, ymid, r) {
var points = [];
var x = 0;
var y = r;
var pk = 5/4 - r;
while (x < y)
{
if (pk < 0)
{
x++;
pk += 2*x + 1;
}
else
{
x++;
y--;
pk += 2 * (x-y) + 1;
}
points.push(x+xmid, y+ymid);
points.push(x+xmid, -y+ymid);
points.push(-x+xmid, y+ymid);
points.push(-x+xmid, -y+ymid);
points.push(y+xmid, x+ymid);
points.push(y+xmid, -x+ymid);
points.push(-y+xmid, x+ymid);
points.push(-y+xmid, -x+ymid);
}
var cbuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cbuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(points),
gl.STATIC_DRAW);
gl.drawArrays(gl.POINTS, 0, points.length/2);
var positionAttribLocation = gl.getAttribLocation(program,
'vertPosition');
var colorAttribLocation = gl.getAttribLocation(program,
'vertColor');
gl.vertexAttribPointer(
positionAttribLocation, // Attribute location
2, // Number of elements per attribute
gl.FLOAT, // Type of elements
gl.FALSE,
5 * Float32Array.BYTES_PER_ELEMENT, // Size of an individual vertex
0 // Offset from the beginning of a single vertex to this attribute
);
gl.enableVertexAttribArray(positionAttribLocation);
gl.enableVertexAttribArray(colorAttribLocation);
return points;
}
circle(0.6, 0.6, 0.18);
circle(0.9, 0.6, 0.18);
circle(0.5, 0.4, 0.18);
circle(1.0, 0.4, 0.18);
circle(0.75, 0.4, 0.18);
circle(0.75, 0.4, 0.18);
}
START();
<canvas id="sky"></canvas>
This is what my console log is saying:
6WebGL: INVALID_OPERATION: useProgram: program not
valid
6WebGL: INVALID_OPERATION: drawArrays: no valid shader
program in use
12WebGL: INVALID_OPERATION: getAttribLocation: program
not linked
You can clearly see that I am linking and using the program at the very beginning. So what gives?
There's more than one issue with the code
The shaders are not compiled
After setting the shader source with gl.shaderSource you need
to compile them with gl.compileShader. You should also
be checking for errors by calling gl.getShaderParameter(shader, gl.COMPILE_STATUS)
and you should be checking for errors after linking by calling
gl.getProgramParameter(program, gl.LINK_STATUS)
gl.drawArrays is called before setting the attributes
The code is enabling 2 attributes but only supplying data for 1 attribute.
The code is drawing gl.POINTS but the vertex shader is not setting gl_PointSize
I also don't really understand your circle code but since I don't know what it's really trying to do I can't fix it.
And finally you should probably read some tutorials on WebGL
I'd also suggest you use multiline template literals for your shaders
const vertexShaderText = `
precision mediump float;
attribute vec2 vertPosition;
attribute vec3 vertColor;
varying vec3 fragColor;
void main()
{
fragColor = vertColor;
gl_Position = vec4(vertPosition, 0.0, 1.0);
gl_PointSize = 5.;
}
`;
const fragmentShaderText = `
precision mediump float;
varying vec3 fragColor;
void main()
{
gl_FragColor = vec4(fragColor, 1.0);
}
`;
const start = function () {
console.log('This is working');
const canvas = document.getElementById('sky');
const gl = canvas.getContext('webgl');
if (!gl) {
alert('Your browser does not support WebGL');
return;
}
gl.clearColor(.3, .3, .7, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//create a shader program
const program = createProgram(gl, vertexShaderText, fragmentShaderText);
gl.useProgram(program);
const circle = function (xmid, ymid, r) {
const points = [];
let x = 0;
let y = r;
let pk = 5/4 - r;
while (x < y)
{
if (pk < 0)
{
x++;
pk += 2*x + 1;
}
else
{
x++;
y--;
pk += 2 * (x-y) + 1;
}
points.push(x+xmid, y+ymid);
points.push(x+xmid, -y+ymid);
points.push(-x+xmid, y+ymid);
points.push(-x+xmid, -y+ymid);
points.push(y+xmid, x+ymid);
points.push(y+xmid, -x+ymid);
points.push(-y+xmid, x+ymid);
points.push(-y+xmid, -x+ymid);
}
const cbuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cbuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(points), gl.STATIC_DRAW);
const positionAttribLocation = gl.getAttribLocation(program, 'vertPosition');
const colorAttribLocation = gl.getAttribLocation(program, 'vertColor');
gl.vertexAttribPointer(
positionAttribLocation, // Attribute location
2, // Number of elements per attribute
gl.FLOAT, // Type of elements
gl.FALSE,
0, // Size of an individual vertex
0 // Offset from the beginning of a single vertex to this attribute
);
gl.enableVertexAttribArray(positionAttribLocation);
// you probably meant to supply colors for this attribute
// since if you wanted a constant color you'd have probably
// used a uniform but since you didn't we'll set a constant
// color
gl.vertexAttrib4f(colorAttribLocation, 1, 0, 0, 1);
gl.drawArrays(gl.POINTS, 0, points.length/2);
return points;
}
circle(0.6, 0.6, 0.18);
circle(0.9, 0.6, 0.18);
circle(0.5, 0.4, 0.18);
circle(1.0, 0.4, 0.18);
circle(0.75, 0.4, 0.18);
circle(0.75, 0.4, 0.18);
}
function createProgram(gl, vertexShaderText, fragmentShaderText) {
// Create shaders
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderText);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderText);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
return null;
}
return program;
}
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
start();
<canvas id="sky"></canvas>
I am developing a small program that load 3d models using assimp, but it does not render the model. At first I thought that vertices and indices were not loaded correctly but this is not the case ( I printed on a txt file vertices and indices). I think that the probem might be with the position of the model and camera. The application does not return any error, it runs properly.
Vertex Struct:
struct Vertex {
XMFLOAT3 position;
XMFLOAT2 texture;
XMFLOAT3 normal;
};
Input layout:
D3D12_INPUT_ELEMENT_DESC inputLayout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};
Vertices, texcoords, normals and indices loader:
model = new ModelMesh();
std::vector<XMFLOAT3> positions;
std::vector<XMFLOAT3> normals;
std::vector<XMFLOAT2> texCoords;
std::vector<unsigned int> indices;
model->LoadMesh("beast.x", positions, normals,
texCoords, indices);
// Create vertex buffer
if (positions.size() == 0)
{
MessageBox(0, L"Vertices vector is empty.",
L"Error", MB_OK);
}
Vertex* vList = new Vertex[positions.size()];
for (size_t i = 0; i < positions.size(); i++)
{
Vertex vert;
XMFLOAT3 pos = positions[i];
vert.position = XMFLOAT3(pos.x, pos.y, pos.z);
XMFLOAT3 norm = normals[i];
vert.normal = XMFLOAT3(norm.x, norm.y, norm.z);
XMFLOAT2 tex = texCoords[i];
vert.texture = XMFLOAT2(tex.x, tex.y);
vList[i] = vert;
}
int vBufferSize = sizeof(vList);
Build of the camera and views:
XMMATRIX tmpMat = XMMatrixPerspectiveFovLH(45.0f*(3.14f/180.0f), (float)Width / (float)Height, 0.1f, 1000.0f);
XMStoreFloat4x4(&cameraProjMat, tmpMat);
// set starting camera state
cameraPosition = XMFLOAT4(0.0f, 2.0f, -4.0f, 0.0f);
cameraTarget = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f);
cameraUp = XMFLOAT4(0.0f, 1.0f, 0.0f, 0.0f);
// build view matrix
XMVECTOR cPos = XMLoadFloat4(&cameraPosition);
XMVECTOR cTarg = XMLoadFloat4(&cameraTarget);
XMVECTOR cUp = XMLoadFloat4(&cameraUp);
tmpMat = XMMatrixLookAtLH(cPos, cTarg, cUp);
XMStoreFloat4x4(&cameraViewMat, tmpMat);
cube1Position = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f);
XMVECTOR posVec = XMLoadFloat4(&cube1Position);
tmpMat = XMMatrixTranslationFromVector(posVec);
XMStoreFloat4x4(&cube1RotMat, XMMatrixIdentity());
XMStoreFloat4x4(&cube1WorldMat, tmpMat);
Update function :
XMStoreFloat4x4(&cube1WorldMat, worldMat);
XMMATRIX viewMat = XMLoadFloat4x4(&cameraViewMat); // load view matrix
XMMATRIX projMat = XMLoadFloat4x4(&cameraProjMat); // load projection matrix
XMMATRIX wvpMat = XMLoadFloat4x4(&cube1WorldMat) * viewMat * projMat; // create wvp matrix
XMMATRIX transposed = XMMatrixTranspose(wvpMat); // must transpose wvp matrix for the gpu
XMStoreFloat4x4(&cbPerObject.wvpMat, transposed); // store transposed wvp matrix in constant buffer
memcpy(cbvGPUAddress[frameIndex], &cbPerObject, sizeof(cbPerObject));
VERTEX SHADER:
struct VS_INPUT
{
float4 pos : POSITION;
float2 tex: TEXCOORD;
float3 normal : NORMAL;
};
struct VS_OUTPUT
{
float4 pos: SV_POSITION;
float2 tex: TEXCOORD;
float3 normal: NORMAL;
};
cbuffer ConstantBuffer : register(b0)
{
float4x4 wvpMat;
};
VS_OUTPUT main(VS_INPUT input)
{
VS_OUTPUT output;
output.pos = mul(input.pos, wvpMat);
return output;
}
Hope it is a long code to read but I don't understand what is going wrong with this code. Hope somebody can help me.
A few things to try/check:
Make your background clear color grey. That way, if you are drawing black triangles you will see them.
Turn backface culling off in the rendering state, in case your triangles are back to front.
Turn depth test off in the rendering state.
Turn off alpha blending.
You don't show your pixel shader, but try writing a constant color to see if your lighting calculation is broken.
Use NVIDIA's nSight tool, or the Visual Studio Graphics debugger to see what your graphics pipeline is doing.
Those are usually the things I try first...