Related
I am learning OpenGL ES and use for this the book "Lean OpenGL ES for Mobile Game and Graphics Development" written by Mehta. He firstly shows how to build a simple project, goes over and adds orthoMatrix, then 3D, and in the end he explains how to use this all together with a texture. I am wondering if it is possible to use a texture without a matrix. I must say I tried it, the program did not crash, but the the texture was completely scattered and disorted - as if the vertexData was wrong. So my first question is if it is teoretically possible?
UPDATE 1
This code below represents an application which is able to show the camera preview on a texture. With the use of a matrix it works fine, but the use without a matrix results in the screen as shown on the picture.
this is the texture vertex shader and the texture fragment shader.
attribute vec4 a_Position;
attribute vec2 a_TextureCoordinates;
varying vec2 v_TextureCoordinates;
void main()
{
v_TextureCoordinates = a_TextureCoordinates;
gl_Position = a_Position;
}
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES u_TextureUnit;
varying vec2 v_TextureCoordinates;
void main()
{
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
}
The texture loader
public class TextureHelper {
public static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
public static int loadTexture() {
final int[] textureObjectsId = new int[1];
GLES20.glGenTextures(1, textureObjectsId, 0);
if (textureObjectsId[0] == 0 ) {
return 0;
}
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureObjectsId[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
return textureObjectsId[0];
The locations and uniforms
public class TextureShaderProgram extends ShaderProgram {
private final int uTextureUnitLocation;
// Attribute locations
private final int aPositionLocation;
private final int aTextureCoordinatesLocation;
public TextureShaderProgram(Context context) {
super(context, R.raw.texture_vertex_shader, R.raw.texture_fragment_shader);
uTextureUnitLocation = GLES20.glGetUniformLocation(program, U_TEXTURE_UNIT);
aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION);
aTextureCoordinatesLocation = GLES20.glGetAttribLocation(program, A_TEXTURE_COORDINATES);
}
public void setUniforms(int textureId) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
GLES20.glUniform1i(uTextureUnitLocation, 0);
}
public int getPositionAttributeLocation() {
return aPositionLocation;
}
public int getTextureCoordinatesAttributeLocation() {
return aTextureCoordinatesLocation;
}
}
The vertexData (triangle fan)
public class Table {
private static final int POSITION_COMPONENT_COUNT = 2;
private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
private static final int STRIDE = (POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT * BYTES_PER_FLOAT);
private static final float[] VERTEXDATA = {
0f, 0f, 0.5f, 0.5f, //middle
-0.5f, -0.8f, 1f, 0.1f,//bottom left
0.5f, -0.8f, 1f, 0.9f, //bottom right
0.5f, 0.8f, 0f, 0.9f,//top right
-0.5f, 0.8f, 0f, 0.1f, // top left
-0.5f, -0.8f, 1f, 0.1f, // bottom left
};
Do you need more? Leave comment so I can post the rest if needed.
You will normally need some form of transform to animate the vertices in your scene. This is nearly always a matrix, because they can efficiently represent any desirable transform, but it doesn't have to be.
It is rare for the texture coordinate itself to be modified by a matrix - normally the texture is "fixed" on the model so the coordinate is just passed through the vertex shader without modification.
I'm trying to make a simple app on Android Studio using the NDK, JNI to call C++ code that load and display an image. I have managed to create the surface and draw a simple Triangle.
Now, I'm looking for a way to load and display an image in OpenGL ES 3.0 using C++. I have done the search around but all of them is either too complex to me or outdated or written in Java. It would be great if someone could guide me with a simple example.
After working around, I finally make it. Below is my C++ source code. I use stb_image library to load the image.
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// OpenGL ES 3.0 code
#include <jni.h>
#include <android/log.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <GLES3/gl3ext.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "stb_image.h"
#define LOG_TAG "libgl2jni"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
GLuint mTexture, VAO;// Create reference Id for the texture
GLuint gProgram;
GLuint gvPositionHandle;
static void printGLString(const char *name, GLenum s) {
const char *v = (const char *) glGetString(s);
LOGI("GL %s = %s\n", name, v);
}
static void checkGlError(const char* op) {
for (GLint error = glGetError(); error; error
= glGetError()) {
LOGI("after %s() glError (0x%x)\n", op, error);
}
}
auto gVertexShader =
"#version 300 es\n"
"layout (location=0) in vec3 position;\n"
"layout (location=1) in vec3 color;\n"
"layout (location=2) in vec2 texCoord;\n"
"out vec3 ourColor;\n"
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position,1.0f); // Add the xOffset to the x position of the vertex position\n"
"ourColor = color;\n"
"TexCoord= vec2(texCoord.x,1.0f-texCoord.y);\n"
"}";
auto gFragmentShader =
"#version 300 es\n"
"in vec3 ourColor;\n"
"in vec2 TexCoord;\n"
"out vec4 color;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
"color = texture(ourTexture , TexCoord);\n"
"}\n";
GLuint loadShader(GLenum shaderType, const char* pSource) {
GLuint shader = glCreateShader(shaderType);
if (shader) {
glShaderSource(shader, 1, &pSource, NULL);
glCompileShader(shader);
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen) {
char* buf = (char*) malloc(infoLen);
if (buf) {
glGetShaderInfoLog(shader, infoLen, NULL, buf);
LOGE("Could not compile shader %d:\n%s\n",
shaderType, buf);
free(buf);
}
glDeleteShader(shader);
shader = 0;
}
}
}
return shader;
}
GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) { // Load and Bind Fragments to Progam and link program then return result
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
if (!vertexShader) {
return 0;
}
GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
if (!pixelShader) {
return 0;
}
GLuint program = glCreateProgram();
if (program) {
glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
glLinkProgram(program);
GLint linkStatus = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE) {
GLint bufLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
if (bufLength) {
char* buf = (char*) malloc(bufLength);
if (buf) {
glGetProgramInfoLog(program, bufLength, NULL, buf);
LOGE("Could not link program:\n%s\n", buf);
free(buf);
}
}
glDeleteProgram(program);
program = 0;
}
}
return program;
}
bool setupGraphics(int w, int h) {
printGLString("Version", GL_VERSION);
printGLString("Vendor", GL_VENDOR);
printGLString("Renderer", GL_RENDERER);
printGLString("Extensions", GL_EXTENSIONS);
LOGI("setupGraphics(%d, %d)", w, h);
gProgram = createProgram(gVertexShader, gFragmentShader);
if (!gProgram) {
LOGE("Could not create program.");
return false;
}
gvPositionHandle = glGetAttribLocation(gProgram, "position");
checkGlError("glGetAttribLocation");
LOGI("glGetAttribLocation(\"position\") = %d\n",
gvPositionHandle);
glViewport(0, 0, w, h);
checkGlError("glViewport");
return true;
}
GLfloat recVertices[] = {
// Positions // Colors // Texture Coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Top Right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // Top Left
};
GLuint indices[] = { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
void initBuffers()
{
GLuint VBOs[2], EBO; // Initialize an buffer to store all the verticles and transfer them to the GPU
glGenVertexArrays (1,&VAO); // Generate VAO
glGenBuffers(1, VBOs); // Generate VBO
glGenBuffers(1, &EBO); // Generate EBO
glBindVertexArray (VAO);// Bind the Vertex Array
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);//Bind verticles array for OpenGL to use
glBufferData(GL_ARRAY_BUFFER, sizeof(recVertices), recVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//Bind the indices for information about drawing sequence
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 1. set the vertex attributes pointers
// Position Attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color Attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//Texture Coordinate Attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0);//3. Unbind VAO
}
void generateTexture()
{
glGenTextures(1 , &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture);// Bind our 2D texture so that following set up will be applied
//Set texture wrapping parameter
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_MIRRORED_REPEAT);
//Set texture Filtering parameter
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
//Load the image
int picWidth,picHeight,n;
unsigned char* image = stbi_load("/storage/emulated/sdcard/Lighthouse.jpg", &picWidth, &picHeight, &n,0);
if (image == NULL ) {
LOGI("Failed to load image: %s", stbi_failure_reason());
}
//Generate the image
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB , picWidth , picHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(image);// Free the reference to the image
glBindTexture(GL_TEXTURE_2D,0); //Unbind 2D textures
}
void renderFrame() {
static float grey;
grey += 0.01f;
if (grey > 1.0f) {
grey = 0.0f;
}
generateTexture();
glClearColor(grey+0.05f, grey-0.03f, grey+0.02f, grey-0.04f);
checkGlError("glClearColor");
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
checkGlError("glClear");
glUseProgram(gProgram);
checkGlError("glUseProgram");
/*glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, recVertices);
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(gvPositionHandle);
checkGlError("glEnableVertexAttribArray");
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
checkGlError("glDrawArrays");*/
glActiveTexture(GL_TEXTURE0);
checkGlError("glActiveTexture");
glBindTexture(GL_TEXTURE_2D,mTexture);
checkGlError("glBindTexture");
GLint mlocation = glGetUniformLocation(gProgram,"ourTexture");
checkGlError("glGetUniformLocation");
glUniform1i(mlocation,0);
checkGlError("glUniform1i");
initBuffers();
glBindVertexArray(VAO);
checkGlError("glBindVertexArray");
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
}
extern "C" {
JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_init(JNIEnv * env, jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_step(JNIEnv * env, jobject obj);
};
JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_init(JNIEnv * env, jobject obj, jint width, jint height)
{
setupGraphics(width, height);
}
JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_step(JNIEnv * env, jobject obj)
{
renderFrame();
}
I am writing a small program to simulate animation. I use QGLWidget to display a dynamic image to mimic picture animation. The basic idea is to use texture and update it through QGLFamebufferOject::blitFramebuffer. Each time, the image array will be changed and then frame buffer will be changed.
The code can run and the image can be moved forward, but image has chopping problem, or flicking, not smooth.
Following is the code for a class:
GLWidget::GLWidget(QWidget *parent) : QGLWidget(QGLFormat(), parent)
{
makeCurrent();
if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) {
QGLFramebufferObjectFormat format;
render_fbo = new QGLFramebufferObject(640, 480, format);
texture_fbo = new QGLFramebufferObject(640, 480);
} else {
render_fbo = new QGLFramebufferObject(640, 480);
texture_fbo = render_fbo;
}
tile_list = glGenLists(1);
glNewList(tile_list, GL_COMPILE);
glBegin(GL_QUADS);
{
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
}
glEnd();
glEndList();
backbufferImg = new unsigned char[640 * 480 * sizeof(unsigned char) * 3];
}
GLWidget::~GLWidget()
{
}
void GLWidget::initializeGL()
{
}
void GLWidget::resizeGL(int width, int height)
{
}
void GLWidget::paintGL()
{
}
void GLWidget::saveGLState()
{
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
}
void GLWidget::restoreGLState()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
}
void GLWidget::changeTextureImage(int nextColumn, int direction)
{
// code about chaning backbufferImg
// ...
// call draw
draw();
}
void GLWidget::draw()
{
makeCurrent();
QPainter p(this); // used for text overlay
// save the GL state set for QPainter
saveGLState();
QPainter fbo_painter(render_fbo);
QImage renderImg(backbufferImg, 640, 480, QImage::Format_RGB888);
fbo_painter.begin(render_fbo);
QRect rect(640, 480);
fbo_painter.drawImage(rect, renderImg, rect);
fbo_painter.end();
if (render_fbo != texture_fbo) {
QGLFramebufferObject::blitFramebuffer(texture_fbo, rect, render_fbo, rect);
} else {
// qDebug() << "render_fbo == texture_fbo";
}
// draw into the GL widget
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, width(), height());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, texture_fbo->texture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glScalef(1.0f, 1.0f, 1.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glCallList(tile_list);
glPopMatrix();
// restore the GL state that QPainter expects
restoreGLState();
glFinish();
}
Qt's QGLWidget expects that you perform all drawing operations from its overloaded paintGL function so that it iteracts nicely with Qt's double buffer management.
Also why are you taking that detour over a FBO to update a texture? This is highly inefficient and introduces a lot of synchronization points. Use a Pixel Buffer Object and update the texture with glTexSubImage2D.
Thank you very much! I have changed the code and put the drawing code inside paintGL and didn't use FBO's blit method. MUch better, but still need to improve the code. The following is the code:
GLWidget::GLWidget(QWidget *parent) :
QGLWidget(QGLFormat(), parent)
{
makeCurrent();
fbo = new QGLFramebufferObject(WIDTH, HEIGHT);
tile_list = glGenLists(1);
glNewList(tile_list, GL_COMPILE);
glBegin(GL_QUADS);
{
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
}
glEnd();
glEndList();
backbufferImg = new unsigned char[WIDTH * HEIGHT * sizeof(unsigned char) * 3];
}
GLWidget::~GLWidget()
{
glDeleteLists(tile_list, 1);
delete fbo;
delete backbufferImg;
}
void GLWidget::initializeGL()
{
}
void GLWidget::resizeGL(int width, int height)
{
}
void GLWidget::paintGL()
{
glViewport(0, 0, fbo->size().width(), fbo->size().height());
glMatrixMode(GL_MODELVIEW);
// render to the framebuffer object
fbo->bind();
glBindTexture(GL_TEXTURE_2D, refreshTexture);
glCallList(tile_list);
fbo->release();
//////////////////////////////////////////////////////////////////////
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, width(), height());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, fbo->texture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glScalef(1.0f, 1.0f, 1.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glCallList(tile_list);
glPopMatrix();
// restore the GL state that QPainter expects
restoreGLState();
glFinish();
}
void GLWidget::saveGLState()
{
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
}
void GLWidget::restoreGLState()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
}
void GLWidget::refreshTextureImage(int nextColumn, int direction)
{
// upadte backbufferImg
// add code...
QImage renderImg(backbufferImg, WIDTH, HEIGHT, QImage::Format_RGB888);
refreshTexture = bindTexture(renderImg);
updateGL();
}
I will try the method you suggested. But I think framebuffer and pixel buffer in the same level. It means there is no much performance difference. For glTexSubImage2D, I am not quite sure, I need to check it.
Thank you so much.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Image loading using openGL, SOIL
while running the source code below, it displays just a wite quad without an image.
I tried to open an image called: foto.
I placed the image-file in the folder of the program.
bool* keyStates = new bool[256];
GLuint texture[0];
void resize(int height, int width) {
const float ar = (float) width / (float) height;
glViewport(0, 10, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 90.0);
//gluLookAt(0, 2, 0, -1, 1, -3, 0, 1, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
}
void keyOperations (void) {
if (!keyStates['a']) {}
}
static void Draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f);
texture[0] = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
(
"foto.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
// allocate a texture name
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glutSwapBuffers();
}
void keyPressed (unsigned char key, int x, int y) {
keyStates[key] = false;
}
void keyUp (unsigned char key, int x, int y) {
keyStates[key] = true;
}
int main(int argc, char **argv)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
glutCreateWindow("ugh fml");
glutReshapeFunc(resize);
glutDisplayFunc(Draw);
glutKeyboardFunc(keyPressed);
glutKeyboardUpFunc(keyUp);
/////////////////////////////////////
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glutMainLoop();
}
I get the same behavior if the image file (foto.png) is not located in the program's working directory. But when I add the image to the program's working directory, the quad is textured properly. Try either 1) adding the texture image to the program's working directory or 2) changing the program's working directory to the directory where the texture file is located.
I am running this code on a PC (compiled in code::blocks 10.05)
When i used to do basic OpenGL code with GLUT (GL Utiltiy Toolkit) Everything worked fine.
Now that i'm running OpenGL code through the SDL Framework when i try to change the z-axis (third parameter) of the translation function the location of a geometric primitive (quad) the 3D space appears to have no depth and either shows covering the complete screen or completely disappears when the depth gets to a certain point.
Am i missing anything? :/
#include <sdl.h>
#include <string>
#include "sdl_image.h"
#include "SDL/SDL_opengl.h"
#include <gl\gl.h>
// Declare Constants
const int FRAMES_PER_SECOND = 60;
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
// Create Event Listener
SDL_Event event;
// Declare Variable Used To Control How Deep Into The Screen The Quad Is
GLfloat zpos(0);
// Loop Switches
bool gamestarted(false);
bool exited(false);
// Prototype For My GL Draw Function
void drawstuff();
// Code Begins
void init_GL() {
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glViewport(0, 0, 640, 513); // Viewport Change
glOrtho(0, 640, 0, 513, -1.0, 1.0); // Puts Stuff Into View
}
bool init() {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_SetVideoMode(640, 513, 32, SDL_OPENGL);
return true;
}
void drawstuff() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, zpos);
glColor3f(0.5f,0.5f,0.5f);
glBegin(GL_QUADS);
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glEnd();
}
int main (int argc, char* args[]) {
init();
init_GL();
while(exited == false) {
while( SDL_PollEvent( &event ) ) {
if( event.type == SDL_QUIT ) {
exited = true;
}
if( event.type == SDL_MOUSEBUTTONDOWN ) {
zpos-=.1;
}
}
glClear( GL_COLOR_BUFFER_BIT);
drawstuff();
SDL_GL_SwapBuffers();
}
SDL_Quit();
return 0;
}
When you say depth, do you refer to a perspective effect? You need to use a perspective projection matrix (see gluPerspective) if you want things farther away to appear smaller.
You're currently using orthographic projection (glOrtho), which does not have any perspective effect.
I don't know the reason for your problem, but I find a problem in your code.
After rendering one frame, you cleared the color framebuffer, but you forgot to clear the depth buffer.So, use glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); in your main function and see the effect.
I think I know the anwser:
In Orthographic projection(after projection and perspective divide):
Zb = -2/(f-n) -(f+n)/((f-n)*Z)
Zb:z value in depth buffer
Z: z value of your vertex you give
In your situation: glOrtho(0, 640, 0, 513, -1.0, 1.0);
f = 1.0, n = -1.0
so your Zb would always be -2/(f - n) = -1, this causes all your primitives's depth the same.
You can reference to Red book's Appendix C.2.5.There is a matrix for orthographic projection, and after that is perspective divide.
There is another tips to keep in mind in perspective projection that zNear value cannot be set to zero, which causes all primitives' depth value in depth buffer to be same as this one.