2016-04-11 4 views
2

Ich bin ein einfach OpenGL app nehme ich vor, dass ein Ikosaeder hatte hatte und es über zu machen, um eine Textur zu ändern und dann diese Textur auf dem Bildschirm zeichnen. Irgendwie, während der Rendering zu Textur, wenn ich glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); anrufen meine gesamte Textur wird getönt von meinem glClearColor. Hier ist die Gesamtheit dessen, was ich habe:glClearColor tönt meine gesamte Textur?

#include <stdio.h> 
#include <GL/glew.h> 
#include <GL/freeglut.h> 
#include <GL/gl.h> 
#include <GL/glu.h> 
#include <iostream> 
#include <fstream> 
#include <Windows.h> 

using namespace std; 

void SetupRenderTarget(); 
void EnableLighting(); 
GLuint LoadProgram(char*, char*); 
void draw(); 
float UpdateDelta(); 
unsigned long getFileLength(ifstream&); 
GLuint compileshader(char* file, GLenum shader_type); 
int loadshader(char*, GLchar**, unsigned long*); 

GLuint quad_vertexbuffer; 
GLuint frame = 0; 
GLuint FrameBuffer = 0; 
GLuint texID = 0; 
GLuint timeID = 0; 
GLuint renderedTexture; 

int main(int argc, char** argv) { 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE); 
    glutInitWindowSize(300, 300); 
    glutInitWindowPosition(100, 500); 
    glutCreateWindow("Hello World"); 
    glutDisplayFunc(draw); 

    glewInit(); 

    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_MULTISAMPLE); 
    glEnable(GL_TEXTURE_2D); 
    glViewport(0, 0, 300, 300); 
    EnableLighting(); 
    SetupRenderTarget(); 

    frame = LoadProgram((char*)"passthrough.shader", (char*)"framebuffer.shader"); 
    texID = glGetUniformLocation(frame, "renderedTexture"); 
    timeID = glGetUniformLocation(frame, "time"); 

    glutMainLoop(); 
    return 0; 
} 

void SetupRenderTarget() { 
    glGenFramebuffers(1, &FrameBuffer); 
    glBindFramebuffer(GL_FRAMEBUFFER, FrameBuffer); 
    glGenTextures(1, &renderedTexture); 
    glBindTexture(GL_TEXTURE_2D, renderedTexture); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 300, 300, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

    GLuint DepthBuffer; 
    glGenRenderbuffers(1, &DepthBuffer); 
    glBindRenderbuffer(GL_RENDERBUFFER, DepthBuffer); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 300, 300); 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, DepthBuffer); 

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0); 
    GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; 
    glDrawBuffers(1, DrawBuffers); 

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 
    cout << "Frame Buffer Error!" << endl; 
    return; 
    } 

    cout << "Frame Buffer Setup" << endl; 
} 

void EnableLighting() { 
    float light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; 
    float light_position[] = { -1.0, 1.0, 1.0, 0.0 }; 
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); 
    glLightfv(GL_LIGHT0, GL_POSITION, light_position); 
    glEnable(GL_LIGHT0); 
    glEnable(GL_LIGHTING); 

    glEnable(GL_CULL_FACE); 
    glCullFace(GL_BACK); 

    glEnable(GL_COLOR_MATERIAL); 
} 

GLuint LoadProgram(char* vertex, char* fragment) { 
    GLuint ProgramObject = 0; 
    GLuint v, f; 
    if (vertex != 0) v = compileshader(vertex, GL_VERTEX_SHADER); 
    if (fragment != 0) f = compileshader(fragment, GL_FRAGMENT_SHADER); 

    ProgramObject = glCreateProgram(); 
    if (v != -1) glAttachShader(ProgramObject, v); 
    if (f != -1) glAttachShader(ProgramObject, f); 

    cout << "Linking Shader..." << endl; 
    glLinkProgram(ProgramObject); 

    cout << "Done!" << endl; 
    return ProgramObject; 
} 

GLuint compileshader(char* file, GLenum shader_type) { 
    cout << "Loading Shader: " << file << endl; 
    char* src; 
    unsigned long src_length = 0; 
    int err = loadshader(file, &src, &src_length); 
    if (err != 0) return -1;// something went wrong 

    cout << "Creating Shader..." << endl; 
    GLuint shader = glCreateShader(shader_type); 
    cout << "Loading Shader..." << endl; 
    glShaderSourceARB(shader, 1, (const char**)&src, (const int*)&src_length); 
    cout << "Compiling Shader..." << endl; 
    glCompileShaderARB(shader); 
    delete[] src; 

    GLint compiled; 
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 
    if (!compiled) { 
    GLint blen = 0; 
    GLsizei slen = 0; 

    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &blen); 
    if (blen > 1) { 
     GLchar* compiler_log = (GLchar*)malloc(blen); 
     glGetInfoLogARB(shader, blen, &slen, compiler_log); 
     cout << "Compiler Log:" << endl << compiler_log << endl; 
     free(compiler_log); 
    } else { 
     cout << "Compile error but could not get log!" << endl; 
    } 
    return -1; 
    } 
    return shader; 
} 

void draw() { 
    static float mytime = 0; 
    float delta = UpdateDelta(); 
    mytime += delta; 

    glBindFramebuffer(GL_FRAMEBUFFER, FrameBuffer); 
    glViewport(0, 0, 300, 300); 

    glLoadIdentity(); 
    float x = 0.5f; 
    glClearColor(x, x, x, 0.0); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glColor3f(0, 1, 0); 

    glRotatef(45, 0, 1, 0); 
    glutSolidIcosahedron(); 

    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
    glViewport(0, 0, 300, 300); 

    glUseProgram(frame); 
    glUniform1i(texID, 0); 
    glUniform1f(timeID, mytime * 10); 

    glLoadIdentity(); 
    glClearColor(0.0, 0.0, 0.0, 0.0); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glColor3f(1, 1, 1); 
    glDisable(GL_LIGHTING); 

    glBegin(GL_QUADS); 
    glTexCoord2f(0.0f, 0.0f); 
    glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left Of The Texture and Quad 
    glTexCoord2f(1.0f, 0.0f); 
    glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right Of The Texture and Quad 
    glTexCoord2f(1.0f, 1.0f); 
    glVertex3f(1.0f, 1.0f, 0.0f); // Top Right Of The Texture and Quad 
    glTexCoord2f(0.0f, 1.0f); 
    glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left Of The Texture and Quad 
    glEnd(); 

    glEnable(GL_LIGHTING); 
    glUseProgram(0); 

    glFlush(); 
    glutSwapBuffers(); 
    glutPostRedisplay(); 
} 

float UpdateDelta() { 
    static int time_since_start = 0; 
    static int last = 0; 
    time_since_start = glutGet(GLUT_ELAPSED_TIME); 

    float ret = (time_since_start - last)/1000.0f; 
    last = time_since_start; 
    return ret; 
} 

unsigned long getFileLength(ifstream& file) { 
    if (!file.good()) return 0; 

    unsigned long pos = (unsigned long)file.tellg(); 
    file.seekg(0, ios::end); 
    unsigned long len = (unsigned long)file.tellg(); 
    file.seekg(ios::beg); 

    return len; 
} 

int loadshader(char* filename, GLchar** ShaderSource, unsigned long* len) { 
    ifstream file; 
    file.open(filename, ios::in); // opens as ASCII! 
    if (!file) return -1; 

    *len = getFileLength(file); 

    if (*len == 0) return -2; // Error: Empty File 

    *ShaderSource = (GLchar*) new char[*len + 1]; 
    if (*ShaderSource == 0) return -3; // can't reserve memory 

             // len isn't always strlen cause some characters are stripped in ascii read... 
             // it is important to 0-terminate the real length later, len is just max possible value... 
    (*ShaderSource)[*len] = 0; 

    unsigned int i = 0; 
    while (file.good()) { 
     (*ShaderSource)[i] = file.get();  // get character from file. 
     if (!file.eof()) { 
      i++; 
     } 
    } 
    (*ShaderSource)[i] = 0; // 0-terminate it at the correct position 
    file.close(); 

    return 0; // No Error 
} 

ich teilweise this tutorial folgende bin und unter Verwendung ihrer Shadern.

passthrough.shader:

#version 330 core 

// Input vertex data, different for all executions of this shader. 
layout(location = 0) in vec3 vertexPosition_modelspace; 

// Output data ; will be interpolated for each fragment. 
out vec2 UV; 

void main() { 
    gl_Position = vec4(vertexPosition_modelspace, 1); 
    UV = (vertexPosition_modelspace.xy + vec2(1, 1))/2.0; 
} 

und framebuffer.shader:

#version 330 core 

in vec2 UV; 

out vec3 color; 

uniform sampler2D renderedTexture; 
uniform float time; 

void main() { 
    color = texture(renderedTexture, UV.xy).rgb; // no change to image 
    //color = texture(renderedTexture, UV + 0.005*vec2(sin(time + 300.0*UV.x), cos(time + 300.0*UV.y))).xyz; // wibbly-wobbly version from tutorial 
} 

Ok, ich weiß, dass eine Menge Code ist so hier ist die kurze und süß wie ich verstehen, was los ist.

SetupRenderTarget schafft eine Farbe und eine Tiefe die gleiche Größe wie mein Fenster (300x300) puffern.

EnableLighting nur Positionen und beleuchtet die Szene. Es scheint gut zu funktionieren und hat nichts mit der Frage zu tun, als eine interessante Sache zu betrachten.

LoadProgram liest in Vektor und Fragment-Quelldateien, stellt sie zusammen, so dass sie in dem gleichen Programm setzt verbindet, das Programm und gibt das Programm-ID, wenn alles gut gegangen ist compileshader und loadshader verwenden. Es scheint auch zu funktionieren.

draw ist, wo das Fleisch des Problems geschieht. Ich kann es setze die FrameBuffer zu verwenden, habe ich die klare Farbe (x verwenden ist, weil ich so müde bin von jedem Parameterwert von 0,0 bis 1,0 zu ändern und wieder zurück), I klar, habe ich die Farbe für meine Ikosaeder, und jetzt Die Szene wird vollständig im Bild gerendert.

Dann fange ich an, mein Programm zu verwenden und auf den eigentlichen "draw to screen" -Frame-Puffer von 0 umzuschalten. Ich lösche diesen Puffer mit schwarz (dieses clear scheint nicht wichtig zu sein, auf was ich es setze, es hat keine Auswirkung), zeichne ich einen weißen Viererkabel ohne Beleuchtung und stelle die Beleuchtung und die Programme für die folgende Schleife zurück.

Ich erhalte keine Compiler-Fehler oder Warnungen zu jeder Zeit während der Ausführung dieses. Das Problem ist, wenn ich glClear() rufe, wenn ich das icosahedron zum Rahmenpuffer rendere, die Farbe tönt die gesamte Beschaffenheit ab. Ich möchte meine x Var auf 0 setzen, so dass ich einen schwarzen Hintergrund hinter einer lebhaften grünen Form habe, aber die gesamte Textur wird schwarz.

Hier ein paar Bilder erzeugt indem nur, dass x var:

x = 1.0f;

x = 1

x = 0,5f;

x = 0.5

x = 0.1f;

x = 0.1

Zu meinem Verständnis, der Hintergrund hinter der Form sollte die klare Farbe reflektieren wird Verdunkelung aber nicht die Form selbst. Es sollte genauso lebendig bleiben wie ein Grün auf dem ersten Bild.

Warum sollte meine klare Farbe beeinflussen, wie das Ikosaeder gezeichnet wird und wie repariere ich es?

Ich kompiliere mit Visual Studio mit NupenGL Bibliotheken auf Win7 x64 und glGetString(GL_VERSION) sagt 4.3.

+0

Ich bin meistens eine ES-Person, aber das ist eine feste/programmierbare Hybride, also: Was garantiert 'glutSolidIcosahedron' beim Texturieren? Es ist wahrscheinlich nicht die Ursache, aber ich möchte ausschließen, dass Sie Ihr Framebuffer-Objekt technisch nicht gleichzeitig gebunden haben, da es "möglich" ist, dass seine Textur abgetastet werden kann (der Test ist möglich, nicht unbedingt das tatsächliche Sampling)). Was eine Ursache für undefiniertes Verhalten ist. Die ursprünglichen Regeln finden Sie unter 4.4.3 von http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt. – Tommy

+0

@Tommy Laut [dieser Seite] (https://www.opengl.org/resources/libraries/glut/spec3/node80.html) Überschwemmung Feste Formen haben alle Normalen, aber nur die Teekanne hat Texturkoordinaten. Natürlich wurde es seit 1996 nicht aktualisiert ... –

+0

Sie können sicher sein, dass dies kein Problem ist, indem Sie den Aufruf entfernen: glEnable (GL_TEXTURE_2D); Ich habe den Code eine Weile angeschaut, aber ich kann auch kein offensichtliches Problem sehen, obwohl ich mich in "alten" OpenGL nicht sehr auskenne. Ich habe deine Frage neu gestellt. –

Antwort

0

Da Sie beim Zeichnen des ICO keine Shader verwenden, verwenden Sie die Standardpipeline. glEnable(GL_TEXTURE_2D); weist die Pipeline an, Texturierung zu verwenden. Also welche Textur hast du gebunden?

Es stellt sich heraus, dass Sie die Textur, die Sie rendern, glBindTexture(GL_TEXTURE_2D, renderedTexture); gebunden haben und nie ungebunden durch Aufruf glBindTexture(GL_TEXTURE_2D, 0);. Sie zeichnen also einen ICO, der seine Texturdaten von dem, zu dem Sie zeichnen, bezieht, der zu diesem Zeitpunkt nur die Hintergrundfarbe (x,x,x) enthält.

Technisch gesehen, denke ich, dass das Lesen von einer Textur während des Schreibens zu undefiniertem Verhalten führt. Auch wenn das Verhalten dieses Mal "korrekt" war, sollten Sie sich nicht darauf verlassen, dass dieses Verhalten konsistent funktioniert.

Als Ergänzung sollten Sie wissen, dass glEnable(GL_COLOR_MATERIAL); bewirkt, dass Ihre Textur mit der Farbe verschmelzen, also ohne diesen Aufruf wäre die ICO (glaube ich) überhaupt nicht grün!