总结:我的原始问题和观察结果后面是英特尔高清显卡4000 GPU的更新工作OpenGL代码。
原始问题: Nvidia NVS 4200m GPU上显示了两个立方体,Intel HD Graphics 4000 GPU上显示了一个立方体。
以下是基于OpenTK示例程序“Open GL 3.0”的源代码。它应该显示两个立方体,用定向光源旋转大约(0,0,0)。
更新:2014年11月17日:以下代码适用于Nvidia和Intel HD Graphics 4000 GPU。
变化:
渲染后取消激活缓冲区和VAO
using System;
using System.Diagnostics;
using System.IO;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace Examples.Tutorial
{
[Example("OpenGL 3.0 v2 2 vao works", ExampleCategory.OpenGL, "3.x", Documentation="HelloGL3 - v2 - create vao first")]
public class HelloGL3v3 : GameWindow
{
string vertexShaderSource = @"
#version 130
precision highp float;
uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
in vec3 in_position;
in vec3 in_normal;
out vec3 normal;
void main(void)
{
//works only for orthogonal modelview
normal = (modelview_matrix * vec4(in_normal, 0)).xyz;
gl_Position = projection_matrix * modelview_matrix * vec4(in_position, 1);
}";
string fragmentShaderSource = @"
#version 130
precision highp float;
const vec3 ambient = vec3(0.1, 0.1, 0.1);
const vec3 lightVecNormalized = normalize(vec3(0.5, 0.5, 20.0));
//const vec3 lightVecNormalized = normalize(vec3(0.5, 0.5, 2.0));
const vec3 lightColor = vec3(0.9, 0.9, 0.7);
in vec3 normal;
out vec4 out_frag_color;
void main(void)
{
float diffuse = clamp(dot(lightVecNormalized, normalize(normal)), 0.0, 1.0);
out_frag_color = vec4(ambient + diffuse * lightColor, 1.0);
}";
int vertexShaderHandle,
fragmentShaderHandle,
shaderProgramHandle,
modelviewMatrixLocation,
projectionMatrixLocation;
Matrix4 projectionMatrix, modelviewMatrix;
public HelloGL3v3() : base(800, 600,
new GraphicsMode(), "OpenGL 3 Example", 0,
DisplayDevice.Default, 3, 2,
GraphicsContextFlags.ForwardCompatible | GraphicsContextFlags.Debug)
{ }
protected override void OnLoad (System.EventArgs e)
{
VSync = VSyncMode.On;
CreateShaders();
CreateVaoOne();
CreateVaoTwo();
// Other state
GL.Enable(EnableCap.DepthTest); E();
GL.ClearColor(System.Drawing.Color.MidnightBlue); E();
}
void CreateShaders()
{
vertexShaderHandle = GL.CreateShader(ShaderType.VertexShader); E();
fragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader); E();
GL.ShaderSource(vertexShaderHandle, vertexShaderSource); E();
GL.ShaderSource(fragmentShaderHandle, fragmentShaderSource); E();
GL.CompileShader(vertexShaderHandle); E();
GL.CompileShader(fragmentShaderHandle); E();
Debug.WriteLine(GL.GetShaderInfoLog(vertexShaderHandle));
Debug.WriteLine(GL.GetShaderInfoLog(fragmentShaderHandle));
// Create program
shaderProgramHandle = GL.CreateProgram(); E();
GL.AttachShader(shaderProgramHandle, vertexShaderHandle); E();
GL.AttachShader(shaderProgramHandle, fragmentShaderHandle); E();
//BindAttribLocation() for shader needs to be done before linking the shader program
GL.BindAttribLocation(shaderProgramHandle, 0, "in_position"); E();
GL.BindAttribLocation(shaderProgramHandle, 1, "in_normal"); E();
GL.LinkProgram(shaderProgramHandle); E();
Debug.WriteLine(GL.GetProgramInfoLog(shaderProgramHandle));
GL.UseProgram(shaderProgramHandle); E();
// get uniform locations
projectionMatrixLocation = GL.GetUniformLocation(shaderProgramHandle, "projection_matrix"); E();
modelviewMatrixLocation = GL.GetUniformLocation(shaderProgramHandle, "modelview_matrix"); E();
float aspectRatio = ClientSize.Width / (float)(ClientSize.Height);
Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspectRatio, 1, 100, out projectionMatrix);
modelviewMatrix = Matrix4.LookAt(new Vector3(0, 13, 15), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
GL.UniformMatrix4(projectionMatrixLocation, false, ref projectionMatrix); E();
GL.UniformMatrix4(modelviewMatrixLocation, false, ref modelviewMatrix); E();
}
int vaoHandle,
eboHandle;
int[] indicesVboData = new int[]{
// front face
0, 1, 2, 2, 3, 0,
// top face
3, 2, 6, 6, 7, 3,
// back face
7, 6, 5, 5, 4, 7,
// left face
4, 0, 3, 3, 7, 4,
// bottom face
0, 1, 5, 5, 4, 0,
// right face
1, 5, 6, 6, 2, 1, };
void CreateVaoOne()
{
int positionVboHandle,
normalVboHandle;
Vector3[] positionVboData = new Vector3[]{
new Vector3(-1.0f, -1.0f, 1.0f),
new Vector3( 1.0f, -1.0f, 1.0f),
new Vector3( 1.0f, 1.0f, 1.0f),
new Vector3(-1.0f, 2.0f, 1.0f),
new Vector3(-1.0f, -1.0f, -1.0f),
new Vector3( 1.0f, -1.0f, -1.0f),
new Vector3( 1.0f, 1.0f, -1.0f),
new Vector3(-1.0f, 1.0f, -1.0f) };
// GL3 allows us to store the vertex layout in a "vertex array object" (VAO).
// This means we do not have to re-issue VertexAttribPointer calls
// every time we try to use a different vertex layout - these calls are
// stored in the VAO so we simply need to bind the correct VAO.
GL.GenVertexArrays(1, out vaoHandle); E();
GL.BindVertexArray(vaoHandle); E();
//----------------------------------------------------------------------------
{
GL.GenBuffers(1, out positionVboHandle); E();
GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle); E();
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, new IntPtr(positionVboData.Length * Vector3.SizeInBytes), positionVboData, BufferUsageHint.StaticDraw); E();
GL.EnableVertexAttribArray(0); E();
GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle); E();
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0); E();
//GL.BindAttribLocation(shaderProgramHandle, 0, "in_position"); E();
}
//----------------------------------------------------------------------------
{
GL.GenBuffers(1, out normalVboHandle); E();
GL.BindBuffer(BufferTarget.ArrayBuffer, normalVboHandle); E();
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, new IntPtr(positionVboData.Length * Vector3.SizeInBytes), positionVboData, BufferUsageHint.StaticDraw); E();
GL.EnableVertexAttribArray(1); E();
GL.BindBuffer(BufferTarget.ArrayBuffer, normalVboHandle); E();
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0); E();
//GL.BindAttribLocation(shaderProgramHandle, 1, "in_normal"); E();
}
{
GL.GenBuffers(1, out eboHandle); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle); E();
GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(sizeof(uint) * indicesVboData.Length), indicesVboData, BufferUsageHint.StaticDraw); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle); E();
}
//----------------------------------------------------------------------------
GL.BindBuffer(BufferTarget.ArrayBuffer, 0); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); E();
GL.BindVertexArray(0); E();
}
int vaoHandle2,
eboHandle2;
int[] indicesVboData2 = new int[]{
// front face
0, 1, 2, 2, 3, 0,
// top face
3, 2, 6, 6, 7, 3,
// back face
7, 6, 5, 5, 4, 7,
// left face
4, 0, 3, 3, 7, 4,
// bottom face
0, 1, 5, 5, 4, 0,
// right face
1, 5, 6, 6, 2, 1, };
void CreateVaoTwo()
{
int positionVboHandle2,
normalVboHandle2;
Vector3[] positionVboData2 = new Vector3[]{
new Vector3(-0.5f, -0.5f, 0.5f),
new Vector3( 0.5f, -0.5f, 0.5f),
new Vector3( 0.5f, 0.5f, 0.5f),
new Vector3(-0.5f, 0.5f, 5.5f),
new Vector3(-0.5f, -0.5f, -0.5f),
new Vector3( 0.5f, -0.5f, -0.5f),
new Vector3( 0.5f, 0.5f, -0.5f),
new Vector3(-0.5f, 0.5f, -0.5f) };
Vector3[] normalsVboData2 = new Vector3[]{
new Vector3(-1.0f, -1.0f, 1.0f),
new Vector3( 1.0f, -1.0f, 1.0f),
new Vector3( 1.0f, 1.0f, 1.0f),
new Vector3(-1.0f, 1.0f, 1.0f),
new Vector3(-1.0f, -1.0f, -1.0f),
new Vector3( 1.0f, -1.0f, -1.0f),
new Vector3( 1.0f, 1.0f, -1.0f),
new Vector3(-1.0f, 1.0f, -1.0f) };
//translate the points in the second cube away from the origin
for (int i = 0; i < positionVboData2.Length; i++)
positionVboData2[i] = Vector3.Add(positionVboData2[i], new Vector3(2.0f, 0f, 0f));
GL.GenVertexArrays(1, out vaoHandle2); E();
GL.BindVertexArray(vaoHandle2); E();
//----------------------------------------------------------------------------
//vertex array
GL.GenBuffers(1, out positionVboHandle2); E();
GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle2); E();
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, new IntPtr(positionVboData2.Length * Vector3.SizeInBytes), positionVboData2, BufferUsageHint.StaticDraw); E();
GL.EnableVertexAttribArray(0); E();
GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle2); E();
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0); E();
//GL.BindAttribLocation(shaderProgramHandle, 0, "in_position"); E();
//------------------------------------------------------------
//normals array
GL.GenBuffers(1, out normalVboHandle2); E();
GL.BindBuffer(BufferTarget.ArrayBuffer, normalVboHandle2); E();
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, new IntPtr(normalsVboData2.Length * Vector3.SizeInBytes), normalsVboData2, BufferUsageHint.StaticDraw); E();
GL.EnableVertexAttribArray(1); E();
GL.BindBuffer(BufferTarget.ArrayBuffer, normalVboHandle2); E();
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0); E();
//GL.BindAttribLocation(shaderProgramHandle, 1, "in_normal"); E();
//------------------------------------------------------------
//element (index) array
GL.GenBuffers(1, out eboHandle2); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle2); E();
GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(sizeof(uint) * indicesVboData2.Length), indicesVboData2, BufferUsageHint.StaticDraw); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle2); E();
//------------------------------------------------------------
GL.BindBuffer(BufferTarget.ArrayBuffer, 0); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); E();
GL.BindVertexArray(0); E();
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
if ((Keyboard[OpenTK.Input.Key.ControlLeft]) || (Keyboard[OpenTK.Input.Key.ControlRight]))
return;
Matrix4 rotation = Matrix4.CreateRotationY((float)e.Time);
Matrix4.Mult(ref rotation, ref modelviewMatrix, out modelviewMatrix);
GL.UniformMatrix4(modelviewMatrixLocation, false, ref modelviewMatrix);
if (Keyboard[OpenTK.Input.Key.Escape])
Exit();
}
protected override void OnRenderFrame(FrameEventArgs e)
{
GL.Viewport(0, 0, Width, Height); E();
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); E();
//GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
GL.BindVertexArray(vaoHandle); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle); E();
GL.DrawElements(BeginMode.Triangles, indicesVboData.Length, DrawElementsType.UnsignedInt, IntPtr.Zero); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
GL.BindVertexArray(0);
//-----------------------------------------------------------------------
GL.BindVertexArray(vaoHandle2); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle2); E();
GL.DrawElements(BeginMode.Triangles, indicesVboData2.Length, DrawElementsType.UnsignedInt, IntPtr.Zero); E();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); E();
GL.BindVertexArray(0); E();
SwapBuffers(); E();
}
[STAThread]
public static void Main()
{
using (HelloGL3v3 example = new HelloGL3v3())
{
Utilities.SetWindowTitle(example);
example.Run(30);
}
}
private void E()
{
ErrorCode errorCode = GL.GetError();
if (errorCode == ErrorCode.NoError)
return;
throw new Exception("Error code - " + errorCode.ToString()); // some open GL Error
}
}
}