Use more than 1 shader on display - c#
This question is based on the Giawa tutorials on OpenGL. I have completed tut6 & tut9 separately, but now I want to combine the two. I.e. I want that cube spinning while a bunch of stars is floating around. However, I'm pretty new two OpenGL but it looks like they use different types of shaders. So I wrote two shaders, but now when I try to run it my cube is transparent and the stars does not display. Is it possible to display both on screen at the same time correctly? Below is my code.
using System;
using Tao.FreeGlut;
using OpenGL;
using System.Windows;
using System.Windows.Forms;
using System.Collections.Generic;
namespace OpenGLTutorial6
{
class Program
{
private static int width = 1280, height = 720;
private static ShaderProgram program, program_2;
private static VBO<Vector3> cube, top_pyramid, bottom_pyramid, cubeNormals, bottom_pyramidNormals, top_pyramidNormals, star;
private static VBO<Vector2> cubeUV, top_pyramidUV, bottom_pyramidUV, starUV;
private static VBO<int> cubeQuads, top_pyramidTrianlges, bottom_pyramidTrianlges, starQuads;
private static bool fullscreen = false;
private static bool left, right, up, down;
private static List<Star> stars = new List<Star>();
private static Random generator = new Random(Environment.TickCount);
private static float theta = (float)Math.PI / 2, phi = (float)Math.PI / 2;
private static Texture crateTexture,
brickTexture,
cracked_glassTexture,
desert_surfaceTexture,
numbersTexture,
ziggyTexture,
starTexture;
private static System.Diagnostics.Stopwatch watch;
private static float angle;
private static int rotate = 1;
private static bool lighting = true;
private class Star
{
public float angle;
public float dist;
public Vector3 color;
public Star(float Angle, float Distance, Vector3 Color)
{
this.angle = Angle;
this.dist = Distance;
this.color = Color;
}
}
static void Main(string[] args)
{
// create an OpenGL window
Glut.glutInit();
Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH);
Glut.glutInitWindowSize(width, height);
Glut.glutCreateWindow("SCREENSAVER");
// provide the Glut callbacks that are necessary for running this tutorial
Glut.glutIdleFunc(OnRenderFrame);
//Glut.glutIdleFunc(OnRenderFrame_2);
Glut.glutDisplayFunc(OnDisplay);
//<<<<<<<<<<<<< KEYBOARD FUNCTIONS
Glut.glutSpecialFunc(new Glut.SpecialCallback(OnKeyPress));
Glut.glutKeyboardFunc(OnKeyboardDown);
Glut.glutKeyboardUpFunc(OnKeyboardUp);
//<<<<<<<<<<<<< DISPOSE
Glut.glutCloseFunc(OnClose);
// enable depth testing to ensure correct z-ordering of our fragments
Gl.Enable(EnableCap.DepthTest);
Gl.Disable(EnableCap.DepthTest);
Gl.Enable(EnableCap.Blend);
Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.One);
//<<<<<<<<<<< COMPILE SHADER PROGRAMS
program = new ShaderProgram(VertexShader, FragmentShader);
program_2 = new ShaderProgram(VertexShader_2, FragmentShader_2);
//set the view and projection matrix, which are static throughout this tutorial
program.Use();
program["projection_matrix"].SetValue(Matrix4.CreatePerspectiveFieldOfView(0.45f, (float)width / height, 0.1f, 1000f));
program["view_matrix"].SetValue(Matrix4.LookAt(new Vector3(0, 0, 10), Vector3.Zero, Vector3.Up));
program["light_direction"].SetValue(new Vector3(1, 1, 1));
program["enable_lighting"].SetValue(lighting);
program_2.Use();
program_2["projection_matrix"].SetValue(Matrix4.CreatePerspectiveFieldOfView(0.45f, (float)width / height, 0.1f, 1000f));
program_2["view_matrix"].SetValue(Matrix4.LookAt(new Vector3(0, 0, 20), Vector3.Zero, Vector3.Up));
//<<<<<<<<< LOAD TEXTURES
crateTexture = new Texture("crate.jpg");
brickTexture = new Texture("bricks.jpg");
cracked_glassTexture = new Texture("crack.jpg");
desert_surfaceTexture = new Texture("desert.jpg");
numbersTexture = new Texture("numbers.jpg");
ziggyTexture = new Texture("ziggy.jpg");
starTexture = new Texture("star.bmp");
// each star is simply a quad
star = new VBO<Vector3>(new Vector3[] { new Vector3(-1, -1, 0), new Vector3(1, -1, 0), new Vector3(1, 1, 0), new Vector3(-1, 1, 0) });
starUV = new VBO<Vector2>(new Vector2[] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1) });
starQuads = new VBO<int>(new int[] { 0, 1, 2, 3 }, BufferTarget.ElementArrayBuffer);
// create 50 stars for this tutorial
int numStars = 50;
for (int i = 0; i < numStars; i++)
{
stars.Add(new Star(0, (float)i / numStars * 4f, new Vector3(generator.NextDouble(), generator.NextDouble(), generator.NextDouble())));
}
// create a crate with vertices and UV coordinates
cube = new VBO<Vector3>(new Vector3[]
{
new Vector3(-1.5, 0, -0.5), new Vector3(-0.5, 1, -0.5), new Vector3(-0.5, 1, 0.5), new Vector3(-1.5, 0, 0.5),
new Vector3(-0.5, 1, -0.5), new Vector3(0.5, 1, -0.5), new Vector3(0.5, 1, 0.5), new Vector3(-0.5, 1, 0.5),
new Vector3(0.5, 1, -0.5), new Vector3(1.5, 0, -0.5), new Vector3(1.5, 0, 0.5), new Vector3(0.5, 1, 0.5),
new Vector3(1.5, 0, -0.5), new Vector3(1.5, 0, 0.5), new Vector3(0.5, -1, 0.5), new Vector3(0.5, -1, -0.5),
new Vector3(0.5, -1, 0.5), new Vector3(0.5, -1, -0.5), new Vector3(-0.5, -1, -0.5), new Vector3(-0.5, -1, 0.5),
new Vector3(-0.5, -1, -0.5), new Vector3(-0.5, -1, 0.5), new Vector3(-1.5, 0, 0.5), new Vector3(-1.5, 0, -0.5)
});
cubeUV = new VBO<Vector2>(new Vector2[] {
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1) });
top_pyramid = new VBO<Vector3>(new Vector3[]
{
new Vector3(-1.5, 0, -0.5), new Vector3(-0.5, 1, -0.5), new Vector3(0, 0, -1.5),
new Vector3(-0.5, 1, -0.5), new Vector3(0.5, 1, -0.5), new Vector3(0, 0, -1.5),
new Vector3(0.5, 1, -0.5), new Vector3(1.5, 0, -0.5), new Vector3(0, 0, -1.5),
new Vector3(1.5, 0, -0.5), new Vector3(0.5, -1, -0.5), new Vector3(0, 0, -1.5),
new Vector3(0.5, -1, -0.5), new Vector3(-0.5, -1, -0.5), new Vector3(0, 0, -1.5),
new Vector3(-0.5, -1, -0.5), new Vector3(-1.5, 0, -0.5), new Vector3(0, 0, -1.5)
});
top_pyramidUV = new VBO<Vector2>(new Vector2[] {
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1)});
bottom_pyramid = new VBO<Vector3>(new Vector3[]
{
new Vector3(-1.5, 0, 0.5), new Vector3(-0.5, 1, 0.5), new Vector3(0, 0, 1.5),
new Vector3(-0.5, 1, 0.5), new Vector3(0.5, 1, 0.5), new Vector3(0, 0, 1.5),
new Vector3(0.5, 1, 0.5), new Vector3(1.5, 0, 0.5), new Vector3(0, 0, 1.5),
new Vector3(1.5, 0, 0.5), new Vector3(0.5, -1, 0.5), new Vector3(0, 0, 1.5),
new Vector3(0.5, -1, 0.5), new Vector3(-0.5, -1, 0.5), new Vector3(0, 0, 1.5),
new Vector3(-0.5, -1, 0.5), new Vector3(-1.5, 0, 0.5), new Vector3(0, 0, 1.5)
});
bottom_pyramidUV = new VBO<Vector2>(new Vector2[] {
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1),
new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1)});
cubeNormals = new VBO<Vector3>(new Vector3[] {
new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0),
new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0),
new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(0, 0, 1),
new Vector3(0, 0, -1), new Vector3(0, 0, -1), new Vector3(0, 0, -1), new Vector3(0, 0, -1),
new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), new Vector3(-1, 0, 0),
new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0)
});
top_pyramidNormals = new VBO<Vector3>(new Vector3[]{
new Vector3(0,1,0), new Vector3(0,1,0), new Vector3(0,1,0), new Vector3(0,1,0),
new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0),
new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(0, 0, 1),
new Vector3(0, 0, -1), new Vector3(0, 0, -1), new Vector3(0, 0, -1),
new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), new Vector3(-1, 0, 0),
new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0)
});
bottom_pyramidNormals = new VBO<Vector3>(new Vector3[]{
new Vector3(0,1,0), new Vector3(0,1,0), new Vector3(0,1,0), new Vector3(0,1,0),
new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0),
new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(0, 0, 1),
new Vector3(0, 0, -1), new Vector3(0, 0, -1), new Vector3(0, 0, -1),
new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), new Vector3(-1, 0, 0),
new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0)
});
cubeQuads = new VBO<int>(new int[] { 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15,
16, 17, 18, 19,
20, 21, 22, 23 }, BufferTarget.ElementArrayBuffer);
top_pyramidTrianlges = new VBO<int>(new int[] {
0,1,2,
3,4,5,
6,7,8,
9,10,11,
12,13,14,
15,16,17}, BufferTarget.ElementArrayBuffer);
bottom_pyramidTrianlges = new VBO<int>(new int[] {
0,1,2,
3,4,5,
6,7,8,
9,10,11,
12,13,14,
15,16,17}, BufferTarget.ElementArrayBuffer);
watch = System.Diagnostics.Stopwatch.StartNew();
Gl.BindTexture(desert_surfaceTexture);
Glut.glutMainLoop();
}
private static void OnClose()
{
// dispose of all of the resources that were created
//must still update
cube.Dispose();
cubeUV.Dispose();
top_pyramid.Dispose();
top_pyramidTrianlges.Dispose();
cubeQuads.Dispose();
crateTexture.Dispose();
program.DisposeChildren = true;
program.Dispose();
}
private static void OnDisplay()
{
}
private static void OnRenderFrame()
{
// calculate how much time has elapsed since the last frame
watch.Stop();
float deltaTime = (float)watch.ElapsedTicks / System.Diagnostics.Stopwatch.Frequency;
watch.Restart();
// use the deltaTime to adjust the angle of the cube
angle += deltaTime;
// set up the OpenGL viewport and clear both the color and depth bits
Gl.Viewport(0, 0, width, height);
Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// use our shader program and bind the crate texture
Gl.UseProgram(program);
//<<<<<<<<<<<< TOP PYRAMID
// set the transformation of the top_pyramid
program["model_matrix"].SetValue(Matrix4.CreateRotationY(angle * rotate));
program["enable_lighting"].SetValue(lighting);
// bind the vertex positions, UV coordinates and element array
Gl.BindBufferToShaderAttribute(top_pyramid, program, "vertexPosition");
Gl.BindBufferToShaderAttribute(top_pyramidNormals, program, "vertexNormal");
Gl.BindBufferToShaderAttribute(top_pyramidUV, program, "vertexUV");
Gl.BindBuffer(top_pyramidTrianlges);
// draw the textured top_pyramid
Gl.DrawElements(BeginMode.Triangles, top_pyramidTrianlges.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
//<<<<<<<<<< CUBE
// set the transformation of the cube
program["model_matrix"].SetValue(Matrix4.CreateRotationY(angle *rotate));
program["enable_lighting"].SetValue(lighting);
// bind the vertex positions, UV coordinates and element array
Gl.BindBufferToShaderAttribute(cube, program, "vertexPosition");
Gl.BindBufferToShaderAttribute(cubeNormals, program, "vertexNormal");
Gl.BindBufferToShaderAttribute(cubeUV, program, "vertexUV");
Gl.BindBuffer(cubeQuads);
// draw the textured cube
Gl.DrawElements(BeginMode.Quads, cubeQuads.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
//<<<<<<<<<<<< BOTTOM PYRAMID
// set the transformation of the bottom_pyramid
program["model_matrix"].SetValue(Matrix4.CreateRotationY(angle * rotate));
program["enable_lighting"].SetValue(lighting);
// bind the vertex positions, UV coordinates and element array
Gl.BindBufferToShaderAttribute(bottom_pyramid, program, "vertexPosition");
Gl.BindBufferToShaderAttribute(bottom_pyramidNormals, program, "vertexNormal");
Gl.BindBufferToShaderAttribute(bottom_pyramidUV, program, "vertexUV");
Gl.BindBuffer(bottom_pyramidTrianlges);
// draw the textured bottom_pyramid
Gl.DrawElements(BeginMode.Triangles, bottom_pyramidTrianlges.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
Glut.glutSwapBuffers();
}
private static void OnRenderFrame_2()
{
watch.Stop();
float deltaTime = (float)watch.ElapsedTicks / System.Diagnostics.Stopwatch.Frequency;
watch.Restart();
// perform rotation of the scene depending on keyboard input
if (right) phi += deltaTime;
if (left) phi -= deltaTime;
if (up) theta += deltaTime;
if (down) theta -= deltaTime;
if (theta < 0) theta += (float)Math.PI * 2;
// set up the OpenGL viewport and clear both the color and depth bits
Gl.Viewport(0, 0, width, height);
Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
//<<<<<<<<< STARS
// make sure the shader program and texture are being used
Gl.UseProgram(program_2);
Gl.BindTexture(starTexture);
// calculate the camera position using some fancy polar co-ordinates
Vector3 position = 20 * new Vector3(Math.Cos(phi) * Math.Sin(theta), Math.Cos(theta), Math.Sin(phi) * Math.Sin(theta));
Vector3 upVector = ((theta % (Math.PI * 2)) > Math.PI) ? Vector3.Up : Vector3.Down;
program_2["view_matrix"].SetValue(Matrix4.LookAt(position, Vector3.Zero, upVector));
// loop through the stars, drawing each one
for (int i = 0; i < stars.Count; i++)
{
// set the position and color of this star
program_2["model_matrix"].SetValue(Matrix4.CreateTranslation(new Vector3(stars[i].dist, 0, 0)) * Matrix4.CreateRotationZ(stars[i].angle));
program_2["color"].SetValue(stars[i].color);
Gl.BindBufferToShaderAttribute(star, program_2, "vertexPosition");
Gl.BindBufferToShaderAttribute(starUV, program_2, "vertexUV");
Gl.BindBuffer(starQuads);
Gl.DrawElements(BeginMode.Quads, starQuads.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
// update the position of the star
stars[i].angle += (float)i / stars.Count * deltaTime * 2;
stars[i].dist -= 0.2f * deltaTime;
// if we've reached the center then move this star outwards and give it a new color
if (stars[i].dist < 0f)
{
stars[i].dist += 5f;
stars[i].color = new Vector3(generator.NextDouble(), generator.NextDouble(), generator.NextDouble());
}
}
Glut.glutSwapBuffers();
}
public static void OnKeyPress(int theKey, int x, int y)
{
switch (theKey)
{
//<<<<<<< ROTATE
case Glut.GLUT_KEY_F5:
{
rotate += 1;
Console.WriteLine("Hallo!");
}
break;
case Glut.GLUT_KEY_F6:
{
rotate -= 1;
}
break;
//<<<<<<<<<< TEXTURES
case Glut.GLUT_KEY_F7:
{
Gl.BindTexture(cracked_glassTexture);
}
break;
case Glut.GLUT_KEY_F8:
{
Gl.BindTexture(desert_surfaceTexture);
}
break;
case Glut.GLUT_KEY_F9:
{
Gl.BindTexture(brickTexture);
}
break;
case Glut.GLUT_KEY_F10:
{
Gl.BindTexture(ziggyTexture);
}
break;
case Glut.GLUT_KEY_F11:
{
Gl.BindTexture(numbersTexture);
}
break;
}
Glut.glutPostRedisplay();
}
private static void OnKeyboardDown(byte key, int x, int y)
{
if (key == 'w') up = true;
else if (key == 's') down = true;
else if (key == 'd') right = true;
else if (key == 'a') left = true;
else if (key == 27) Glut.glutLeaveMainLoop();
}
private static void OnKeyboardUp(byte key, int x, int y)
{
if (key == 'w') up = false;
else if (key == 's') down = false;
else if (key == 'd') right = false;
else if (key == 'a') left = false;
else if (key == 'f')
{
fullscreen = !fullscreen;
if (fullscreen) Glut.glutFullScreen();
else
{
Glut.glutPositionWindow(0, 0);
Glut.glutReshapeWindow(1280, 720);
}
}
}
public static string VertexShader = #"
#version 130
in vec3 vertexPosition;
in vec3 vertexNormal;
in vec2 vertexUV;
out vec3 normal;
out vec2 uv;
uniform mat4 projection_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;
void main(void)
{
normal = normalize((model_matrix * vec4(floor(vertexNormal), 0)).xyz);
uv = vertexUV;
gl_Position = projection_matrix * view_matrix * model_matrix * vec4(vertexPosition, 1);
}
";
public static string FragmentShader = #"
#version 130
uniform sampler2D texture;
uniform vec3 light_direction;
uniform bool enable_lighting;
in vec3 normal;
in vec2 uv;
out vec4 fragment;
void main(void)
{
float diffuse = max(dot(normal, light_direction), 0);
float ambient = 0.2;
float lighting = (enable_lighting ? max(diffuse, ambient) : 1);
fragment = lighting * texture2D(texture, uv);
}
";
public static string VertexShader_2 = #"
#version 130
in vec3 vertexPosition;
in vec2 vertexUV;
out vec2 uv;
uniform mat4 projection_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;
void main(void)
{
uv = vertexUV;
gl_Position = projection_matrix * (view_matrix * model_matrix * vec4(0, 0, 0, 1) + vec4(vertexPosition.x, vertexPosition.y, vertexPosition.z, 0));
//gl_Position = projection_matrix * view_matrix * model_matrix * vec4(vertexPosition, 1);
}
";
public static string FragmentShader_2 = #"
#version 130
uniform sampler2D texture;
uniform vec3 color;
in vec2 uv;
out vec4 fragment;
void main(void)
{
fragment = vec4(color * texture2D(texture, uv).xyz, 1);
}
";
}
}
Also I've added some other textures that is not in the original tutorials
From scanning through your code, it looks like you have most of what you need. To render both items at the same time, you basically have to add the rendering code that you currently have in OnRenderFrame_2() to OnRenderFrame(). Make sure that you only have one glClear() at the start, and one glutSwapBuffers() at the end.
If the outline of your code currently looks like this:
OnRenderFrame
prepare rendering of Item 1
glViewport
glClear
glUseProgram(program1)
render Item 1
glutSwapBuffers
OnRenderFrame_2
prepare rendering of Item 2
glViewport
glClear
glUseProgram(program2)
render Item 2
glutSwapBuffers
Rearrange it like this:
OnRenderFrame
prepare rendering of Item 1
prepare rendering of Item 2
glViewport
glClear
glUseProgram(program1)
render Item 1
glUseProgram(program2)
render Item 2
glutSwapBuffers
Related
error CS1031: Type expected and error CS1001: Identifier expected
I'm new here and can't understand many things.I'm writing my fist c# code for a Unity game. I saw a tutorial on YouTube of this code and tried as hard as I could to write it correctly.I checked it many times but can't understand how to solve this problem. What's wrong? /tmp/aTDELDegvF.cs(73,40): error CS1031: Type expected /tmp/aTDELDegvF.cs(73,40): error CS1001: Identifier expected using UnityEngine; using System; using System.Collections; using System.Collections.Generic; public class GameController : MonoBehaviour { private CubePos nowCube = new CubePos(0, 1, 0); public float cubeChangePlacespeed = 0.5f; public Transform cubeToPlace; private List<Vector3> allCubesPositions = new List<Vector3>{ new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(-1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, -1), new Vector3(1, 0, 1), new Vector3(-1, 0, -1), new Vector3(-1, 0, 1), new Vector3(1, 0, -1), }; private void Start(){ StartCoroutine(ShowCubePlace()); } IEnumerator ShowCubePlace(){ while(true){ SpawnPositions(); yield return new WaitForSeconds(cubeChangePlacespeed); } } private void SpawnPositions(){ List<Vector3> positions = new List<Vector3>(); if(IsPositionEmpty(new Vector3(nowCube.x + 1, nowCube.y, nowCube.z))) positions.Add(new Vector3(nowCube.x + 1, nowCube.y, nowCube.z)); if(IsPositionEmpty(new Vector3(nowCube.x - 1, nowCube.y, nowCube.z))) positions.Add(new Vector3(nowCube.x - 1, nowCube.y, nowCube.z)); if(IsPositionEmpty(new Vector3(nowCube.x, nowCube.y + 1, nowCube.z))) positions.Add(new Vector3(nowCube.x, nowCube.y + 1, nowCube.z)); if(IsPositionEmpty(new Vector3(nowCube.x, nowCube.y - 1, nowCube.z))) positions.Add(new Vector3(nowCube.x, nowCube.y - 1, nowCube.z)); if(IsPositionEmpty(new Vector3(nowCube.x, nowCube.y, nowCube.z - 1))) positions.Add(new Vector3(nowCube.x, nowCube.y, nowCube.z - 1)); cubeToPlace.position =positions [UnityEngine.Random.Range(0, positions.Count)]; } private bool IsPositionEmpty(Vector3 targetPos){ if(targetPos.y = 0) return false; foreach(Vector3 pos in allCubesPositions){ if(pos.x == targetPos.x && pos.y == targetPos.y && pos.z == targetPos.z) return false; } return true; } } struct CubePos{ public int x, y, z; public CubePos(int x, int y, int z,){ this.x = x; this.y = y; this.z = z; } public Vector3 getVector(){ return new Vector3(x, y, z); } public void setVector(Vector3 pos){ x = Convert.ToInt32(pos.x); y = Convert.ToInt32(pos.y); z = Convert.ToInt32(pos.z); } }
OpenGL - Geometry shader shadow mapping pass performing terribly
I'm calculating shadows for a number of point lights using Variance Shadow Mapping. All 6 faces of the cubemap are rendered in a single pass with a geometry shader, this repeats for each light source, and the whole lot is stored in a cubemap array. This all runs fine, 16 lights at 60fps no problem. Chasing further optimisation, I tried to move the entire process to a single geometry shader pass, only to hit the only 113 vertex output limit of my hardware. Out of curiosity I decided to render 4 lights only (72 emitted vertices) and to my surprise it dropped to 24fps. So why is it that 16 lights with 16 render passes perform significantly better than 4 lights in a single pass? The code is essentially identical. #version 400 core layout(triangles) in; layout (triangle_strip, max_vertices=18) out; uniform int lightID; out vec4 frag_position; uniform mat4 projectionMatrix; uniform mat4 shadowTransforms[6]; void main() { for(int face = 0; face < 6; face++) { gl_Layer = face + (lightID * 6); for(int i=0; i<3; i++) { frag_position = shadowTransforms[face] * gl_in[i].gl_Position; gl_Position = projectionMatrix * shadowTransforms[face] * gl_in[i].gl_Position; EmitVertex(); } EndPrimitive(); } } versus #version 400 core layout(triangles) in; layout (triangle_strip, max_vertices=72) out; out vec4 frag_position; uniform mat4 projectionMatrix; uniform mat4 shadowTransforms[24]; void main() { for (int lightSource = 0; lightSource < 4; lightSource++) { for(int face = 0; face < 6; face++) { gl_Layer = face + (lightSource * 6); for(int i=0; i<3; i++) { frag_position = shadowTransforms[gl_Layer] * gl_in[i].gl_Position; gl_Position = projectionMatrix * shadowTransforms[gl_Layer] * gl_in[i].gl_Position; EmitVertex(); } EndPrimitive(); } } } And public void ShadowMapsPass(Shader shader) { // Setup GL.UseProgram(shader.ID); GL.Viewport(0, 0, CubeMapArray.size, CubeMapArray.size); // Clear the cubemarray array data from the previous frame GL.BindFramebuffer(FramebufferTarget.Framebuffer, shadowMapArray.FBO_handle); GL.ClearColor(Color.White); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); for (int j = 0; j < lights.Count; j++) { // Create the light's view matrices List<Matrix4> shadowTransforms = new List<Matrix4>(); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(1, 0, 0), new Vector3(0, -1, 0))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(-1, 0, 0), new Vector3(0, -1, 0))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 1, 0), new Vector3(0, 0, 1))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, -1, 0), new Vector3(0, 0, -1))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, 1), new Vector3(0, -1, 0))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, -1), new Vector3(0, -1, 0))); // Send uniforms to the shader for (int i = 0; i < 6; i++) { Matrix4 shadowTransform = shadowTransforms[i]; GL.UniformMatrix4(shader.getUniformID("shadowTransforms[" + i + "]"), false, ref shadowTransform); } GL.Uniform1(shader.getUniformID("lightID"), j); DrawScene(shader, false); } } versus public void ShadowMapsPass(Shader shader) { // Setup GL.UseProgram(shader.ID); GL.Viewport(0, 0, CubeMapArray.size, CubeMapArray.size); // Clear the cubemarray array data from the previous frame GL.BindFramebuffer(FramebufferTarget.Framebuffer, shadowMapArray.FBO_handle); GL.ClearColor(Color.White); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // Create the light's view matrices List<Matrix4> shadowTransforms = new List<Matrix4>(); for (int j = 0; j < lights.Count; j++) { shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(1, 0, 0), new Vector3(0, -1, 0))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(-1, 0, 0), new Vector3(0, -1, 0))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 1, 0), new Vector3(0, 0, 1))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, -1, 0), new Vector3(0, 0, -1))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, 1), new Vector3(0, -1, 0))); shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, -1), new Vector3(0, -1, 0))); } // Send uniforms to the shader for (int i = 0; i < shadowTransforms.Count; i++) { Matrix4 shadowTransform = shadowTransforms[i]; GL.UniformMatrix4(shader.getUniformID("shadowTransforms[" + i + "]"), false, ref shadowTransform); } DrawScene(shader, false); }
I'd guess fewer opportunities for parallel code execution in the second form. The first version of the geometry shader generates 18 vertices and must be executed 4 times, but those 4 executions can run in parallel. The second version generates 72 vertices one after the other.
Texturing triangles
I am trying to texture triangle with OpenTK ES with this code using System; using OpenTK; using OpenTK.Graphics.ES11; using OpenTK.Platform.Android; using Android.Content; namespace TexturedTriangle { class GLView1 AndroidGameView { public GLView1(Context context) base(context) { } protected override void CreateFrameBuffer() { base.CreateFrameBuffer(); } Vector2[] TexCoords = { new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1), }; Vector2[] Vertices = { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, 1f), }; int[] Tex = new int[1]; int[] VBOs = new int[2]; protected override void OnLoad(EventArgs e) { base.OnLoad(e); GL.ClearColor(0, 0, 0, 1f); GL.Clear((int)All.ColorBufferBit); GL.MatrixMode(All.Projection); GL.LoadIdentity(); GL.MatrixMode(All.Modelview); GL.LoadIdentity(); GL.Enable(All.Texture2D); GL.GenBuffers(2, VBOs); GL.BindBuffer(All.ArrayBuffer, VBOs[0]); GL.BufferData(All.ArrayBuffer, new IntPtr(Vertices.Length Vector2.SizeInBytes), Vertices, All.StaticDraw); GL.BindBuffer(All.ArrayBuffer, VBOs[1]); GL.BufferData(All.ArrayBuffer, new IntPtr(TexCoords.Length Vector2.SizeInBytes), TexCoords, All.StaticDraw); int[] Data = new int[32 32]; for (int I = 0; I 32 32; I++) { if (I % 3 == 0) Data[I] = 255; if (I % 3 == 1) Data[I] = 65280; if (I % 3 == 2) Data[I] = 16711680; } GL.GenTextures(1, Tex); GL.BindTexture(All.Texture2D, Tex[0]); GL.TexParameter(All.Texture2D, All.TextureMinFilter, (int)All.Nearest); GL.TexParameter(All.Texture2D, All.TextureMagFilter, (int)All.Nearest); GL.TexImage2D(All.Texture2D, 0, 3, 32, 32, 0, All.Rgba, All.UnsignedByte, Data); GL.EnableClientState(All.VertexArray); GL.EnableClientState(All.TextureCoordArray); Run(); } protected override void OnRenderFrame(FrameEventArgs e) { base.OnRenderFrame(e); GL.BindBuffer(All.ArrayBuffer, VBOs[0]); GL.VertexPointer(2, All.Float, BlittableValueType.StrideOf(Vertices) IntPtr.Zero); GL.BindBuffer(All.ArrayBuffer, VBOs[1]); GL.TexCoordPointer(2, All.Float, BilittableValueType.StrideOf(TexCoords), IntPtr.Zero); GL.DrawArrays(All.Triangles, 0, 3); SwapBuffers(); } } } But there is only a white triangle Textured triangle OpenGL ES Meanwhile this code: using System; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenTK; namespace TexturedTriangle { class Program { static void Main() { GameWindow Window = new GameWindow(512, 512, GraphicsMode.Default, "Textured Triangle"); int[] Tex = new int[1]; int[] VBOs = new int[2]; Vector2[] TexCoords = { new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1), }; Vector2[] Vertices = { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, 1f), }; Window.Load += (sender, e) => { GL.ClearColor(0, 0, 0, 1f); GL.Clear(ClearBufferMask.ColorBufferBit); GL.MatrixMode(MatrixMode.Projection); GL.LoadIdentity(); GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); GL.Enable(EnableCap.Texture2D); GL.GenBuffers(2, VBOs); GL.BindBuffer(BufferTarget.ArrayBuffer, VBOs[0]); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(Vertices.Length * Vector2.SizeInBytes), Vertices, BufferUsageHint.StaticDraw); GL.BindBuffer(BufferTarget.ArrayBuffer, VBOs[1]); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(TexCoords.Length * Vector2.SizeInBytes), TexCoords, BufferUsageHint.StaticDraw); int[] Data = new int[32 * 32]; for (int I = 0; I < 32 * 32; I++) { if (I % 3 == 0) Data[I] = 255; if (I % 3 == 1) Data[I] = 65280; if (I % 3 == 2) Data[I] = 16711680; } GL.GenTextures(1, Tex); GL.BindTexture(TextureTarget.Texture2D, Tex[0]); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Three, 32, 32, 0, PixelFormat.Rgba, PixelType.UnsignedByte, Data); GL.EnableClientState(ArrayCap.VertexArray); GL.EnableClientState(ArrayCap.TextureCoordArray); }; Window.RenderFrame += (sender, e) => { GL.Clear(ClearBufferMask.ColorBufferBit); GL.BindBuffer(BufferTarget.ArrayBuffer, VBOs[0]); GL.VertexPointer(2, VertexPointerType.Float, BlittableValueType.StrideOf(Vertices), IntPtr.Zero); GL.BindBuffer(BufferTarget.ArrayBuffer, VBOs[1]); GL.TexCoordPointer(2, TexCoordPointerType.Float, BlittableValueType.StrideOf(TexCoords), IntPtr.Zero); GL.DrawArrays(PrimitiveType.Triangles, 0, 3); Window.SwapBuffers(); }; Window.Run(); } } } Works and output is Textured triangle OpenTK After GL.TexImage2D(); GL.GetError(); gives InvalidValue Documentation: www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml What the problem can be?
I find an error, InternalFormat and Format must match, else InvalidValue is given.
KeyPress causes image to stop moving
I have an OpenGl program that is based on the Giawa tutorials numbers 1-5.Basically I create an image, display it on the screen and make it rotate. All I want to accomplish is add keyboard events to change certain parameters of the image. For instance, in my code I want to press F6 to make the image rotate faster: using System; using Tao.FreeGlut; using OpenGL; using System; using System.Windows; using System.Windows.Forms; namespace OpenGLTutorial5 { class Program { private static int width = 640, height = 480; private static ShaderProgram program; private static VBO<Vector3> top_pyramid, cube, bottom_pyramid; private static VBO<Vector3> top_pyramidColor, cubeColor, bottom_pyramidColor; private static VBO<int> top_pyramidElements, cubeElements, bottom_pyramidElements; private static System.Diagnostics.Stopwatch watch; private static float angle; private static int rotate = 1; static void Main(string[] args) { // create an OpenGL window Glut.glutInit(); Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH); Glut.glutInitWindowSize(width, height); Glut.glutCreateWindow("OpenGL Tutorial"); // provide the Glut callbacks that are necessary for running this tutorial Glut.glutIdleFunc(OnRenderFrame); Glut.glutDisplayFunc(OnDisplay); // Glut.glutKeyboardFunc(new Glut.KeyboardCallback(OnKeyPress)); Glut.glutSpecialFunc(new Glut.SpecialCallback(OnKeyPress)); Glut.glutCloseFunc(OnClose); // enable depth testing to ensure correct z-ordering of our fragments Gl.Enable(EnableCap.DepthTest); // compile the shader program program = new ShaderProgram(VertexShader, FragmentShader); // set the view and projection matrix, which are static throughout this tutorial program.Use(); program["projection_matrix"].SetValue(Matrix4.CreatePerspectiveFieldOfView(0.45f, (float)width / height, 0.1f, 1000f)); program["view_matrix"].SetValue(Matrix4.LookAt(new Vector3(10, 0, 10), Vector3.Zero, Vector3.Up)); top_pyramid = new VBO<Vector3>(new Vector3[] { new Vector3(-1.5, 0, -0.5), new Vector3(-0.5, 1, -0.5), new Vector3(0, 0, -1.5), new Vector3(-0.5, 1, -0.5), new Vector3(0.5, 1, -0.5), new Vector3(0, 0, -1.5), new Vector3(0.5, 1, -0.5), new Vector3(1.5, 0, -0.5), new Vector3(0, 0, -1.5), new Vector3(1.5, 0, -0.5), new Vector3(0.5, -1, -0.5), new Vector3(0, 0, -1.5), new Vector3(0.5, -1, -0.5), new Vector3(-0.5, -1, -0.5), new Vector3(0, 0, -1.5), new Vector3(-0.5, -1, -0.5), new Vector3(-1.5, 0, -0.5), new Vector3(0, 0, -1.5) }); cube = new VBO<Vector3>(new Vector3[] { new Vector3(-1.5, 0, -0.5), new Vector3(-0.5, 1, -0.5), new Vector3(-0.5, 1, 0.5), new Vector3(-1.5, 0, 0.5), new Vector3(-0.5, 1, -0.5), new Vector3(0.5, 1, -0.5), new Vector3(0.5, 1, 0.5), new Vector3(-0.5, 1, 0.5), new Vector3(0.5, 1, -0.5), new Vector3(1.5, 0, -0.5), new Vector3(1.5, 0, 0.5), new Vector3(0.5, 1, 0.5), new Vector3(1.5, 0, -0.5), new Vector3(1.5, 0, 0.5), new Vector3(0.5, -1, 0.5), new Vector3(0.5, -1, -0.5), new Vector3(0.5, -1, 0.5), new Vector3(0.5, -1, -0.5), new Vector3(-0.5, -1, -0.5), new Vector3(-0.5, -1, 0.5), new Vector3(-0.5, -1, -0.5), new Vector3(-0.5, -1, 0.5), new Vector3(-1.5, 0, 0.5), new Vector3(-1.5, 0, -0.5) }); bottom_pyramid = new VBO<Vector3>(new Vector3[] { new Vector3(-1.5, 0, 0.5), new Vector3(-0.5, 1, 0.5), new Vector3(0, 0, 1.5), new Vector3(-0.5, 1, 0.5), new Vector3(0.5, 1, 0.5), new Vector3(0, 0, 1.5), new Vector3(0.5, 1, 0.5), new Vector3(1.5, 0, 0.5), new Vector3(0, 0, 1.5), new Vector3(1.5, 0, 0.5), new Vector3(0.5, -1, 0.5), new Vector3(0, 0, 1.5), new Vector3(0.5, -1, 0.5), new Vector3(-0.5, -1, 0.5), new Vector3(0, 0, 1.5), new Vector3(-0.5, -1, 0.5), new Vector3(-1.5, 0, 0.5), new Vector3(0, 0, 1.5) }); top_pyramidColor = new VBO<Vector3>(new Vector3[] { new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0) }); cubeColor = new VBO<Vector3>(new Vector3[] { new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 1), new Vector3(0,0,1), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 1), new Vector3(0,0,1), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 1), new Vector3(0,0,1), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 1), new Vector3(0,0,1), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 1), new Vector3(0,0,1), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 1), new Vector3(0,0,1), }); bottom_pyramidColor = new VBO<Vector3>(new Vector3[] { new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(1, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(1, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(1, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(1, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(1, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(1, 1, 0) }); top_pyramidElements = new VBO<int>(new int[] { 0,1,2, 3,4,5, 6,7,8, 9,10,11, 12,13,14, 15,16,17}, BufferTarget.ElementArrayBuffer); cubeElements = new VBO<int>(new int[]{ 0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15, 16,17,18,19, 20,21,22,23}, BufferTarget.ElementArrayBuffer); bottom_pyramidElements = new VBO<int>(new int[] { 0,1,2, 3,4,5, 6,7,8, 9,10,11, 12,13,14, 15,16,17}, BufferTarget.ElementArrayBuffer); watch = System.Diagnostics.Stopwatch.StartNew(); Glut.glutMainLoop(); } public static void OnKeyPress(int theKey, int x, int y) { switch (theKey) { case Glut.GLUT_KEY_F6: { rotate += 3; Console.WriteLine("Hallo!"); Console.ReadLine(); } break; } Glut.glutPostRedisplay(); } private static void OnClose() { top_pyramid.Dispose(); top_pyramidColor.Dispose(); top_pyramidElements.Dispose(); program.DisposeChildren = true; program.Dispose(); } private static void OnDisplay() { } private static void OnRenderFrame() { // calculate how much time has elapsed since the last frame watch.Stop(); float deltaTime = (float)watch.ElapsedTicks / System.Diagnostics.Stopwatch.Frequency; watch.Restart(); // use the deltaTime to adjust the angle of the cube and pyramid angle += deltaTime; // set up the OpenGL viewport and clear both the color and depth bits Gl.Viewport(0, 0, width, height); Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // use our shader program Gl.UseProgram(program); //top pyramid program["model_matrix"].SetValue(Matrix4.CreateRotationY(angle * rotate) * Matrix4.CreateTranslation(new Vector3(0.0f, 0, 1))); Gl.BindBufferToShaderAttribute(top_pyramid, program, "vertexPosition"); Gl.BindBufferToShaderAttribute(top_pyramidColor, program, "vertexColor"); Gl.BindBuffer(top_pyramidElements); //top pyramid Gl.DrawElements(BeginMode.Triangles, top_pyramidElements.Count, DrawElementsType.UnsignedInt, IntPtr.Zero); //cubes program["model_matrix"].SetValue(Matrix4.CreateRotationY(angle * rotate) * Matrix4.CreateTranslation(new Vector3(0.0f, 0, 1))); Gl.BindBufferToShaderAttribute(cube, program, "vertexPosition"); Gl.BindBufferToShaderAttribute(cubeColor, program, "vertexColor"); Gl.BindBuffer(cubeElements); //cubes Gl.DrawElements(BeginMode.Quads, cubeElements.Count, DrawElementsType.UnsignedInt, IntPtr.Zero); //bottom pyramid program["model_matrix"].SetValue(Matrix4.CreateRotationY(angle * rotate) * Matrix4.CreateTranslation(new Vector3(0.0f, 0, 1))); Gl.BindBufferToShaderAttribute(bottom_pyramid, program, "vertexPosition"); Gl.BindBufferToShaderAttribute(bottom_pyramidColor, program, "vertexColor"); Gl.BindBuffer(bottom_pyramidElements); //top pyramid Gl.DrawElements(BeginMode.Triangles, bottom_pyramidElements.Count, DrawElementsType.UnsignedInt, IntPtr.Zero); Glut.glutSwapBuffers(); } public static string VertexShader = #" #version 130 in vec3 vertexPosition; in vec3 vertexColor; out vec3 color; uniform mat4 projection_matrix; uniform mat4 view_matrix; uniform mat4 model_matrix; void main(void) { color = vertexColor; gl_Position = projection_matrix * view_matrix * model_matrix * vec4(vertexPosition, 1); } "; public static string FragmentShader = #" #version 130 in vec3 color; out vec4 fragment; void main(void) { fragment = vec4(color, 1); } "; } } The image displays correctly, however when I do press F6 the image stops rotating at all. Any ideas on how to fix this?
I suspect that your problem has nothing to do with OpenGL. Looking at your handler for the F6 key, it has the following code: rotate += 3; Console.WriteLine("Hallo!"); Console.ReadLine(); The last of these lines waits for you to enter text on the standard input. I believe it will block until you enter something. Take out the ReadLine() call, and see if that fixes the problem.
SlimDX Direct3D 11 Indexing Problems
I'm trying to draw an indexed square using SlimDX and Direct3D11. I've managed to draw a square without indices, but when I swap to my indexed version I just get a blank screen. My input layout is set to only take position data (I'm essentially extending from the third tutorial on the SlimDX website) and to draw Triangle Lists. My render loop code is as follows (I am using the triangle.fx pixel and vertex shader files from the tutorial, they take vertex positions (in screen coordinates) and paint them yellow, D3D is shorthand for SlimDX.Direct3D11) //clear the render target context.ClearRenderTargetView(renderTarget, new Color4(0.5f, 0.5f, 1.0f)); context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(mesh.VertexBuffer,12, 0)); context.InputAssembler.SetIndexBuffer(mesh.IndexBuffer, Format.R16_UNorm, 0); context.DrawIndexed(mesh.indices, 0, 0); swapChain.Present(0, PresentFlags.None); "mesh" is a struct that holds a Vertex buffer, Index buffer and vertex count. The data is filled here: Vertex[] vertexes = new Vertex[4]; vertexes[0].Position = new Vector3(0, 0, 0.5f); vertexes[1].Position = new Vector3(0, 0.5f, 0.5f); vertexes[2].Position = new Vector3(0.5f, 0, 0.5f); vertexes[3].Position = new Vector3(0.5f, 0.5f, 0.5f); UInt16[] indexes = { 0, 1, 2, 1, 3, 2 }; DataStream vertices = new DataStream(12 * 4, true, true); foreach (Vertex vertex in vertexes) { vertices.Write(vertex.Position); } vertices.Position = 0; DataStream indices = new DataStream(sizeof(int) * 6, true, true); foreach (UInt16 index in indexes) { indices.Write(index); } indices.Position = 0; mesh = new Mesh(); D3D.Buffer vertexBuffer = new D3D.Buffer(device, vertices, 12 * 4, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); mesh.VertexBuffer = vertexBuffer; mesh.IndexBuffer = new D3D.Buffer(device, indices, 2 * 6, ResourceUsage.Default, BindFlags.IndexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); mesh.vertices = vertexes.GetLength(0); mesh.indices = indexes.Length; All of this is nearly identical to my unindexed square method (with the addition of index buffers and indices, and the removal of two duplicate vertices that aren't needed with indexing), but while the unindexed method draws a square, the indexed method doesn't. My current theory is that there is either something wrong with this line: mesh.IndexBuffer = new D3D.Buffer(device, indices, 2 * 6, ResourceUsage.Default, BindFlags.IndexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); Or these lines: context.InputAssembler.SetIndexBuffer(mesh.IndexBuffer, Format.R16_UNorm, 0); context.DrawIndexed(mesh.indices, 0, 0);
Why don't you just use a vertex and indexbuffer for this simple example? Like this way (Directx9): VertexBuffer vb; IndexBuffer ib; vertices = new PositionColored[WIDTH * HEIGHT]; //vertex creation vb = new VertexBuffer(device, HEIGHT * WIDTH * PositionColored.SizeInBytes, Usage.WriteOnly, PositionColored.Format, Pool.Default); DataStream stream = vb.Lock(0, 0, LockFlags.None); stream.WriteRange(vertices); vb.Unlock(); indices = new short[(WIDTH - 1) * (HEIGHT - 1) * 6]; //indicies creation ib = new IndexBuffer(device, sizeof(int) * (WIDTH - 1) * (HEIGHT - 1) * 6, Usage.WriteOnly, Pool.Default, false); DataStream stream = ib.Lock(0, 0, LockFlags.None); stream.WriteRange(indices); ib.Unlock(); //Drawing device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkSlateBlue, 1.0f, 0); device.BeginScene(); device.VertexFormat = PositionColored.Format; device.SetStreamSource(0, vb, 0, PositionColored.SizeInBytes); device.Indices = ib; device.SetTransform(TransformState.World, Matrix.Translation(-HEIGHT / 2, -WIDTH / 2, 0) * Matrix.RotationZ(angle)); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, WIDTH * HEIGHT, 0, indices.Length / 3); device.EndScene(); device.Present(); I use the mesh in another way (directx9 code again): private void CreateMesh() { meshTerrain = new Mesh(device, (WIDTH - 1) * (HEIGHT - 1) * 2, WIDTH * HEIGHT, MeshFlags.Managed, PositionColored.Format); DataStream stream = meshTerrain.VertexBuffer.Lock(0, 0, LockFlags.None); stream.WriteRange(vertices); meshTerrain.VertexBuffer.Unlock(); stream.Close(); stream = meshTerrain.IndexBuffer.Lock(0, 0, LockFlags.None); stream.WriteRange(indices); meshTerrain.IndexBuffer.Unlock(); stream.Close(); meshTerrain.GenerateAdjacency(0.5f); meshTerrain.OptimizeInPlace(MeshOptimizeFlags.VertexCache); meshTerrain = meshTerrain.Clone(device, MeshFlags.Dynamic, PositionNormalColored.Format); meshTerrain.ComputeNormals(); } //Drawing device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkSlateBlue, 1.0f, 0); device.BeginScene(); device.VertexFormat = PositionColored.Format; device.SetTransform(TransformState.World, Matrix.Translation(-HEIGHT / 2, -WIDTH / 2, 0) * Matrix.RotationZ(angle)); int numSubSets = meshTerrain.GetAttributeTable().Length; for (int i = 0; i < numSubSets; i++) { meshTerrain.DrawSubset(i); } device.EndScene(); device.Present();