Does LWJGL3 and OpenGL need a shader to render? - opengl

My code does not work. I think there is a way to render something on the screen without shaders but how? I heard something about modern OpenGL rendering and how OpenGL needs shaders to render. Help me.
This is my code:
import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL30;
import org.lwjgl.system.MemoryUtil;
public class Main {
public static long window;
public static boolean running = true;
public static void createWindow() {
GLFW.glfwInit();
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GL30.GL_FALSE);
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GL30.GL_TRUE);
window = GLFW.glfwCreateWindow(600, 600, "RenderQuad", 0, 0);
GLFW.glfwMakeContextCurrent(window);
GLFWVidMode vidmode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
GLFW.glfwSetWindowPos(window, (vidmode.width() - 600) / 2, (vidmode.height() - 600) / 2);
GLFW.glfwShowWindow(window);
GL.createCapabilities();
GL30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
public static int vaoID;
public static int vboID;
public static void render() {
float[] vertices = {
-0.5f, 0.5f, 0f,
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, 0.5f, 0f,
-0.5f, 0.5f, 0f
};
vaoID = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoID);
FloatBuffer buffer = MemoryUtil.memAllocFloat(vertices.length);
buffer.put(vertices);
buffer.flip();
vboID = GL30.glGenBuffers();
GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, vboID);
GL30.glBufferData(GL30.GL_ARRAY_BUFFER, buffer, GL30.GL_STATIC_DRAW);
MemoryUtil.memFree(buffer);
GL30.glVertexAttribPointer(0, 3, GL30.GL_FLOAT, false, 0, 0);
GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
}
public static void loopCycle() {
GL30.glClear(GL30.GL_COLOR_BUFFER_BIT);
GL30.glEnableVertexAttribArray(0);
GL30.glBindVertexArray(vaoID);
GL30.glDrawArrays(GL30.GL_TRIANGLES, 0, 6);
GL30.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
public static void clean() {
GL30.glDisableVertexAttribArray(0);
GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
GL30.glDeleteBuffers(vboID);
GL30.glDeleteVertexArrays(vaoID);
glfwDestroyWindow(window);
glfwTerminate();
}
public static void loop() {
GLFW.glfwSwapBuffers(window);
GLFW.glfwPollEvents();
//GL30.glClear(GL30.GL_COLOR_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT);
}
public static void main(String[] args) {
createWindow();
render();
while(running) {
if(GLFW.glfwWindowShouldClose(window)) {running = false; break;}
loopCycle();
loop();
}
clean();
}
}

You do not have the array for vertex attribute 0 enabled when you draw. The array enable state for each vertex attribute is part of the VAO, and when you call glEnableVertexAttribArray it will affect the currently bound VAO.
I have no idea where this comes from, but a lot of people (and seemingly also tutorials) use a scheme like:
Setup() {
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// ... [set up some VBOs and maybe EBO]
glVertexAttribPointer(...);
glBindVertexArray(vao);
}
Draw()
{
glBindVertexArray(vao);
glEnableVertexAttribArray(...);
glDraw...(...);
glDisableVertexAttribArray(...);
glBindVertexArray(0);
}
Now this scheme in principle works, you just mistakenly enable the array while VAO 0 is still bound, and then switch to vao for which no array is enabled at all.
But this scheme is utterly inefficient, the VAO does store this information for a reason: so that you not have to re-specify it each time you want to use it. As a result, the glEnableVertexAttribArray() belongs into the Setup function, and should only be called again if the actual set of vertex attributes for that particular VAO changes (which is never in those examples).
I heard something about modern OpenGL rendering and how OpenGL needs shaders to render.
Yes. Note that shaders were introduced to OpenGL with Version 2.0 in 2004, so that's quite a a strecht of the term modern when it comes to GPU development. You really should consider switching to a 3.2 core profile context, where all the legacy deprecated stuff leftover from the 90s is removed.

Related

OpenGL: vertexArray vs glBegin()

I am following some tutorial on OpenGL and am running into a problem. I constructed a class called Mesh that takes an array of vertices in its constructor and generates vertexarrays and such to do the drawing. The problem is is that I am not seeing anything. Here is the interface:
class Mesh
{
public:
Mesh(Vertex * vertices, size_t numVertices);
virtual ~Mesh();
void Draw();
private:
enum { POSITION_VB, NUM_BUFFERS };
GLuint m_vertexArrayObject;
GLuint m_vertexArrayBuffers;
size_t m_drawCount;
};
and here are the implementations
#include "mesh.h"
Mesh::Mesh(Vertex *vertices, size_t numVertices)
{
m_drawCount = numVertices;
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
glGenBuffers(NUM_BUFFERS, &m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertices[0]), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
void Mesh::Draw()
{
glBindVertexArray(m_vertexArrayObject);
glDrawArrays(GL_TRIANGLES, 0, m_drawCount);
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &m_vertexArrayObject);
}
The Vertex type is a simple class that looks as
class Vertex {
public:
Vertex(glm::vec3 const & pos) { this->pos = pos;}
private:
glm::vec3 pos;
};
If I change the implementation of Mesh::Draw() to
glBegin(GL_TRIANGLES);
glVertex3f(-1.0f, -0.25f, 0.0f); //triangle first vertex
glVertex3f(-0.5f, -0.25f, 0.0f); //triangle second vertex
glVertex3f(-0.75f, 0.25f, 0.0f); //triangle third vertex
glEnd(); //end drawing of triangles
I am getting a triangle printed to the screen. My question is: Does this necessarily mean that there is an error in the implementation of Mesh' member functions, and if so, can anyone spot it? I thought maybe the glBegin method bypasses some error somewhere else in the code that the vertexarray method cannot bypass. I would be grateful for any help. Also, I can post additional code if needed!
The shader code:
#version 120
void main()
{
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
More than likely your Mesh classes destructor is to blame:
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &m_vertexArrayObject);
}
You have an implicit copy constructor, which does a byte-for-byte copy of your class's members whenever a copy of your Mesh is necessary. That byte-for-byte copy includes the name (m_vertexArrayObject) of an OpenGL-managed resource, which means you now have two distinct objects referencing the same resource.
As soon as one of these copies goes out of scope, it will delete the VAO that is still referenced by the original object.
The simplest way to solve this problem is to disable the copy constructor (C++11 has new syntax for this), then you will get a compiler error anytime a copy needs to be made.
private:
Mesh (const Mesh& original); // Copy ctor is inaccessible.
If you really do want to support multiple Mesh objects sharing the same Vertex Array Object, you will need to add reference counting and only free the VAO when the reference count reaches 0.

Custom openGL drawing in cocos2dx (3.2)

Im trying to draw a triangle on screen using openGL on cocos2dx. Currently i have subclassed cocos' Node object inside which i do my drawing.
In the latest version of cocos2dx i cannot override the draw() function instead im trying to override draw(Renderer* renderer, const Mat4 &transform, uint32_t flags) and add Custom commands to the renderer, like so.
const GLfloat vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
void MyNodeSubclass::draw(Renderer* renderer, const Mat4 &transform, uint32_t flags){
CustomCommand *_customCommand = new CustomCommand();
_customCommand->init(_globalZOrder);
_customCommand->func = CC_CALLBACK_0(MyNodeSubclass::drawTriangle, this);
renderer->addCommand(_customCommand);
}
void MyNodeSubclass::drawTriangle(){
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE,0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
And My Load Shader method
void MyNodeSubclass::loadOurShaders(){
GLProgram* myShader = new GLProgram();
myShader->initWithFilenames("shader.vert", "shader.frag");
myShader->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
myShader->link();
myShader->updateUniforms();
}
I dont see the triangle on screen. But I'm able to draw cocos2dx primitive objects (polygons , points , lines) by just swapping out whats in my drawTriangle function but not my vertices using openGL.
What am i missing here?

glUseProgram affecting more than just the VAO

I have successfully created a VAO which produces a triangle which can then be rotated with the mouse (with help from shaders).
My problem comes when I try to draw something else using the standard 'glBegin()' and 'glEnd()' functions. It draws successfully, but now, when I try to rotate the triangle the new drawing also rotates.
I know the problem is somehow fixed using the glUseProgram() function, but I'm not entirely sure why or where it should be added.
Here is my code (I've added it all but the main area of focus should be the display() and init() functions:
#include <GL/glew/glew.h>
#include <GL/freeglut.h>
#include <CoreStructures\CoreStructures.h>
#include <iostream>
#include "texture_loader.h"
#include "shader_setup.h"
using namespace std;
using namespace CoreStructures;
float theta = 0.0f;
bool mDown = false;
int mouse_x, mouse_y;
GLuint myShaderProgram;
GLuint locT; // location of "T" uniform variable in myShaderProgram
GLuint locR; // location of "R" uniform variable in myShaderProgram
GLuint sunPosVBO, sunColourVBO, sunIndicesVBO, sunVAO;
// Packed vertex arrays for the star object
// 1) Position Array - Store vertices as (x,y) pairs
static GLfloat sunVertices [] = {
-0.1f, 0.7f,
0.1f, 0.7f,
0.0f, 0.55f
};
// 2) Colour Array - Store RGB values as unsigned bytes
static GLubyte sunColors [] = {
255, 0, 0, 255,
255, 255, 0, 255,
0, 255, 0, 255
};
// 4) Index Array - Store indices to star vertices - this determines the order the vertices are to be processed
static GLubyte sunVertexIndices [] = {0, 1, 2};
void setupSunVAO(void) {
glGenVertexArrays(1, &sunVAO);
glBindVertexArray(sunVAO);
// copy star vertex position data to VBO
glGenBuffers(1, &sunPosVBO);
glBindBuffer(GL_ARRAY_BUFFER, sunPosVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(sunVertices), sunVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
// copy star vertex colour data to VBO
glGenBuffers(1, &sunColourVBO);
glBindBuffer(GL_ARRAY_BUFFER, sunColourVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(sunColors), sunColors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (const GLvoid*)0);
// enable position, colour buffer inputs
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
// setup star vertex index array
glGenBuffers(1, &sunIndicesVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sunIndicesVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(sunVertexIndices), sunVertexIndices, GL_STATIC_DRAW);
glBindVertexArray(0);
}
void report_version(void) {
int majorVersion, minorVersion;
glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
cout << "OpenGL version " << majorVersion << "." << minorVersion << "\n\n";
}
void init(void) {
// initialise glew library
GLenum err = glewInit();
// ensure glew was initialised successfully before proceeding
if (err==GLEW_OK)
cout << "GLEW initialised okay\n";
else
cout << "GLEW could not be initialised\n";
report_version();
glClearColor(0.0, 0.0, 0.0, 0.0);
//
// setup "sun" VBO and VAO object
//
setupSunVAO();
//
// load shader program
//
myShaderProgram = setupShaders(string("Resources\\Shaders\\basic_vertex_shader.txt"), string("Resources\\Shaders\\basic_fragment_shader.txt"));
// get the index / location of the uniform variables "T" and "R" in shader program "myShaderProgram"
locT = glGetUniformLocation(myShaderProgram, "T");
locR = glGetUniformLocation(myShaderProgram, "R");
// "plug-in" shader into GPU pipeline
glUseProgram(myShaderProgram); // we're in the driving seat!!!!! Our shaders now intercept and process our vertices as part of the GPU rendering pipeline (as shown in the lecture notes)
}
// Example rendering functions - draw objects in local, or modelling coordinates
void drawSun(void) {
glBindVertexArray(sunVAO);
glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_BYTE, (GLvoid*)0);
}
void drawShape()
{
glColor3f(0.0f, 0.6f, 0.2f);
glBegin(GL_POLYGON);
glVertex2f(-1.0f, -1.0f); // Left
glVertex2f(-1.0f, -0.1f);
glVertex2f(-0.9f, -0.05f);
glVertex2f(-0.55f, -0.045f);
glVertex2f(-0.49f, -0.06f);
glVertex2f(-0.4f, -0.055f);
glVertex2f(-0.2f, -0.052f);
glVertex2f(0.0f, -0.02f); // Middle
glVertex2f(0.3f, -0.085f);
glVertex2f(0.5f, -0.08f);
glVertex2f(0.8f, -0.088f);
glVertex2f(1.0f, -0.1f);
glVertex2f(1.0f, -1.0f); // Right
glEnd();
}
//
//
void drawScene()
{
drawSun();
drawShape();
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Setup translation matrix and store in T. Pass this over the the shader with the function glUniformMatrix4fv
GUMatrix4 T = GUMatrix4::translationMatrix(0.01f, 0.01f, 0.0f);
glUniformMatrix4fv(locT, 1, GL_FALSE, (GLfloat*)&T);
// Setup rotation matrix and store in R. Pass this over the the shader with the function glUniformMatrix4fv
GUMatrix4 R = GUMatrix4::rotationMatrix(0.0f, 0.0f, theta);
glUniformMatrix4fv(locR, 1, GL_FALSE, (GLfloat*)&R);
// Draw the scene (the above transformations will be applied to each vertex in the vertex shader)
drawScene();
glutSwapBuffers();
}
void mouseButtonDown(int button_id, int state, int x, int y) {
if (button_id==GLUT_LEFT_BUTTON) {
if (state==GLUT_DOWN) {
mouse_x = x;
mouse_y = y;
mDown = true;
} else if (state == GLUT_UP) {
mDown = false;
}
}
}
void mouseMove(int x, int y) {
if (mDown) {
int dx = x - mouse_x;
int dy = y - mouse_y;
float delta_theta = (float)dy * (3.142f * 0.01f);
theta += delta_theta;
mouse_x = x;
mouse_y = y;
glutPostRedisplay();
}
}
void keyDown(unsigned char key, int x, int y) {
if (key=='r') {
theta = 0.0f;
glutPostRedisplay();
}
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
initCOM();
glutInitContextVersion(3, 3);
glutInitContextProfile (GLUT_COMPATIBILITY_PROFILE);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(800, 800);
glutInitWindowPosition(0, 0);
glutCreateWindow("Combining Transforms");
glutDisplayFunc(display);
glutKeyboardFunc(keyDown);
glutMouseFunc(mouseButtonDown);
glutMotionFunc(mouseMove);
init();
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutMainLoop();
shutdownCOM();
return 0;
}
EDIT
I have an array of x,y vertices and am trying to draw them alongside the above code. For some reason this seems to take vertex data from the sunVAO.
Is there some kind of cache that needs to be cleared? I've searched google and I can't seem to find anyone else who has conflicting VAO and vertex arrays.
(Also, I have checked my code and the vertex data supplied in the array of vertices is correct, they're just not displayed correctly.)
Code:
static GLfloat bottomMarkerVertices[] = {
-0.045f, -0.75f,
0.045f, -0.75f,
-0.07f, -1.0f,
0.07f, -1.0f
};
glVertexPointer(2, GL_FLOAT, 0, bottomMarkerVertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
note: vertex arrays have been enabled.
Assuming you're defining your coordinates in normalized device space (suggested by the apparent absence of a projection matrix), the rendering loop needs to look a little like this:
void drawScene()
{
//update shader parameters for the sun shader if necessary
drawSun();
glUseProgram(0);
// at this point, the PROJECTION and MODELVIEW matrices are both the identity
// so the shape is expected to be in NDCs and is not to be transformed
// at all
drawShape();
glUseProgram(progForSun);
}
Note that I don't advise to mix legacy and modern OpenGL like that. The results of vertex processing triggered by drawShape() are only defined because you're using a compatibility profile context.
The two elements of your scene move together because they are both using the same transformation matrices, specificed by these lines:
// Setup translation matrix and store in T. Pass this over the the shader with the function glUniformMatrix4fv
GUMatrix4 T = GUMatrix4::translationMatrix(0.01f, 0.01f, 0.0f);
glUniformMatrix4fv(locT, 1, GL_FALSE, (GLfloat*)&T);
// Setup rotation matrix and store in R. Pass this over the the shader with the function glUniformMatrix4fv
GUMatrix4 R = GUMatrix4::rotationMatrix(0.0f, 0.0f, theta);
glUniformMatrix4fv(locR, 1, GL_FALSE, (GLfloat*)&R);
If you want drawShape() not to move with the mouse, you need to reset locR with a fixed theta value before you call it.
drawSun();
GUMatrix4 R = GUMatrix4::rotationMatrix(0.0f, 0.0f, 0.0f);
glUniformMatrix4fv(locR, 1, GL_FALSE, (GLfloat*)&R);
drawShape();

NullPointerException On all OpenGL calls LWJGL

Just trying to get a triangle to draw to the screen, following a c++ tutorial. Tried to run the program and I get a NullPointerException on all Opengl calls. Also, I'm following a tutorial for opengl 3 although most of my calls are for earlier versions, is this just how lwjgl is set up, with the functions residing in the version where they originated from?
package examples;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.*;
import java.nio.*;
public class Triangle
{
// An array of 3 vectors which represents 3 vertices
static final float vertexData[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
// This will identify our vertex buffer
int vertexBufferID;
public static void main(String[] args)
{
new Triangle();
}
public Triangle()
{
// Allocate floatBuffer to hold vertex data
FloatBuffer vertexBuffer = FloatBuffer.allocate(9);
// Put float data into buffer and position ready to read
vertexBuffer.put(vertexData).position(0);
// Generate 1 buffer, put the resulting identifier in vertexbuffer
IntBuffer buffers = IntBuffer.allocate(1); // allocate
GL15.glGenBuffers(buffers);
vertexBufferID = buffers.get(0);
// Binds a buffer to the ARRAY_BUFFER(target) (1 at a time) (breaks other bonds)
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferID);
// Give our vertices to OpenGL. (creates store for data bound to target(above))
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertexBuffer,GL15.GL_STATIC_DRAW);
try {
Display.setDisplayMode(new DisplayMode(800,600));
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(0);
}
while(!Display.isCloseRequested())
{
// Render
// 1st attribute buffer : vertices
GL20.glEnableVertexAttribArray(0); // enable vertex attribute index: 0
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferID);
// Specify location of vertex data for index 0
GL33.glVertexAttribP1ui(0, GL11.GL_FLOAT, false, 0);
// Draw the triangle!
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
GL20.glDisableVertexAttribArray(0);
}
}
}
I think that the problem is you have to create the Display before any openGl call.
Try to move
try {
Display.setDisplayMode(new DisplayMode(800,600));
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(0);
}
at the top of the Triangle constructor.

Why doesn't DerelictGL3 draw anything?

I realize that I am not using Glu, nor setting the perspective, but I am using the same normalized device coordinates as McKeeson uses http://www.arcsynthesis.org/gltut/, so I should see the same triangle he gets, only red. I get a black screen and no warnings (I wish they left glDraw functionality for debugging; GL3 is like flying blind until you get out of the smoke!). The code for the drawing is:
module ShaderHub;
import std.stdio;
import std.string;
import derelict.opengl3.gl3;
class ShaderHub{
private bool ok=true;
private GLuint shad=0, vshad=0, fshad=0;
private int voff=0;
private GLuint vbo=0, vao=0;
const float[] v = [ 0.75f, 0.75f, 0.0f, 1.0f,
0.75f, -0.75f, 0.0f, 1.0f,
-0.75f, -0.75f, 0.0f, 1.0f];
public this(){
immutable string vshader = `
#version 330
layout(location = 1) in vec4 pos;
void main(void)
{
gl_Position = pos;
}
`;
immutable string fshader = `
#version 330
void main(void)
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
shad=glCreateProgram();
if(shad==0){
writeln("Error: GL did not assigh main shader program id");
ok=false;
}
vshad=glCreateShader(GL_VERTEX_SHADER);
const char *vptr=toStringz(vshader);
glShaderSource(vshad, 1, &vptr, null);
glCompileShader(vshad);
int status, len;
glGetShaderiv(vshad, GL_COMPILE_STATUS, &status);
if(status==GL_FALSE){
glGetShaderiv(vshad, GL_INFO_LOG_LENGTH, &len);
char[] error=new char[len];
glGetShaderInfoLog(vshad, len, null, cast(char*)error);
writeln(error);
ok=false;
}
fshad=glCreateShader(GL_FRAGMENT_SHADER);
const char *fptr=toStringz(fshader);
glShaderSource(fshad, 1, &fptr, null);
glCompileShader(fshad);
glGetShaderiv(vshad, GL_COMPILE_STATUS, &status);
if(status==GL_FALSE){
glGetShaderiv(fshad, GL_INFO_LOG_LENGTH, &len);
char[] error=new char[len];
glGetShaderInfoLog(fshad, len, null, cast(char*)error);
writeln(error);
ok=false;
}
glAttachShader(shad, vshad);
glAttachShader(shad, fshad);
glLinkProgram(shad);
glGetShaderiv(shad, GL_LINK_STATUS, &status);
if(status==GL_FALSE){
glGetShaderiv(shad, GL_INFO_LOG_LENGTH, &len);
char[] error=new char[len];
glGetShaderInfoLog(shad, len, null, cast(char*)error);
writeln(error);
ok=false;
}
glGenVertexArrays(1, &vao);
if(vao<1){
writeln("Error: GL failed to assign vao id");
ok=false;
}
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
if(vbo<1){
writeln("Error: GL failed to assign vbo id");
ok=false;
}
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, v.length * GL_FLOAT.sizeof, &v[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, cast(void*)voff);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
public void draw(){
glUseProgram(shad);
writeln(glGetAttribLocation(shad, "pos"));//prints 1
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glUseProgram(0);
}
}
Note that the debug writing pos' binding location correctly prints 1. The code setting up SDL and GL is:
import std.stdio;
import derelict.sdl2.sdl;
import derelict.opengl3.gl3;
import EventHub;
import ExposeApp;
pragma(lib, "DerelictUtil.lib");
pragma(lib, "DerelictSDL2.lib");
pragma(lib, "DerelictGL3.lib");
class App{
private ExposeApp funcPtrs;
private EventHub ehub;
private SDL_Window *win;
private SDL_GLContext context;
private int w=600, h=480, fov=55;
private bool running=true;
public this(){
if(!initSDL()){
writeln("Error initializing SDL");
SDL_Quit();
}
initGL();
funcPtrs=new ExposeApp();
funcPtrs.stop=&stopLoop;
funcPtrs.grabMouse=&grabMouse;
funcPtrs.releaseMouse=&releaseMouse;
ehub=new EventHub(funcPtrs);
while(running){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ehub.tick();
SDL_GL_SwapWindow(win);
}
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(win);
SDL_Quit();
}
private void stopLoop(){
running=false;
}
private void grabMouse(){
SDL_ShowCursor(SDL_DISABLE);
SDL_SetWindowGrab(win, SDL_TRUE);
}
private void releaseMouse(){
SDL_ShowCursor(SDL_ENABLE);
SDL_SetWindowGrab(win, SDL_FALSE);
}
private bool initSDL(){
if(SDL_Init(SDL_INIT_VIDEO)< 0){
writefln("Error initializing SDL");
SDL_Quit();
return false;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
win=SDL_CreateWindow("3Doodle", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if(!win){
writefln("Error creating SDL window");
SDL_Quit();
return false;
}
context=SDL_GL_CreateContext(win);
SDL_GL_SetSwapInterval(1);
DerelictGL3.reload();
return true;
}
private void initGL(){
resize(w, h);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glDepthFunc(GL_LEQUAL);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClearDepth(1.0);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
}
private void resize(int w, int h){
//this will contain the makings of the projection matrix, which we go into next tut
glViewport(0, 0, w, h);
}
}
void main(){
try{
DerelictSDL2.load();
}catch(Exception e){
writeln("Error loading SDL2 lib");
}
try{
DerelictGL3.load();
}catch(Exception e){
writeln("Error loading GL3 lib");
}
App a=new App();
}
If anyone has some Derelict3 openGL3 code that actually displays something on screen and were willing to share, because I have googled up and down and can't find any.
Comment to David:
As I said, until I can get something on screen I am flying dark, so what's the point in extending that darkness to cover model loading? I am after the "BASIC" template here; I already have a model loader for the work in C#. The code you linked to is Derelict 1 and doesn't require openGL3, which from what I read, demands vao (hence the reason for their inclusion). But even without that reason, to be able to bind vbo to attribute locations in the vertex shader at initialization, rather than make the glEnableVertexAttribArray plus the glVertexAttribPointer call for every loop for every vbo drawn is a function saving. Culling isn't the problem I checked. So I guess I am still waiting a considered answer!
PS. OK, I am sorry about not clicking the answered button, I didn't realize there was such a thing. I have gone back through old posts and corrected. But your answer to this question Dav1d misses the mark.
Sorry, but this code makes me cry.
I guess this is the first example of the tutorial (according to the shader), my D solution with Derelict2 (also not the best code). Btw, you should disable resizing, this doesn't work most of the time and makes things just harder, especially for a beginner.
I recommend you not to use VAOs, first of all, they bring you nearly no performance boost, make your application harder to maintain and it conflicts with the DSA approach.
Furthermore I also recommend you use some kind of wrapper for the OpenGL API, at least for loading meshes (the Tutorial uses its own helper, if you wanna reimplement it, you have lots of work!). You could use gljm, a library that I wrote, this works pretty well for meshes in the .obj format (it's able to load the sponza scene), also for non-complex meshes in the ply format.
Later on you also need a vector/matrix/quaternion math library, the tutorial uses glm (which you can't really port to D, since it's a C++ template library). gl3n could be an alternative (also written by me).
PS: Please accept answers when you ask questions, not just because I am a reputation-whore, but also so that people can see the best answer immediately (you should also do this with your older questions).
PSĀ²: Maybe your problem is just caused by enabling face-culling.
Found the answer thanks to David at DMD site. The &v in glBufferData(GL_ARRAY_BUFFER, v.length * GL_FLOAT.sizeof, &v, GL_STATIC_DRAW); needs to be changed to a &v[0].
For starters, I don't believe you ever call your draw function (unless that's done via ehub.tick().