#include #include #include #include #include #define mChkGL(X) X; CheckGLError(__LINE__); const GLchar *VertexCode = "#version 130 \n" " \n" "void main() { \n" " gl_Position = gl_Vertex; \n" "} \n" ; const GLchar *FragmentCode = "#version 130 \n" " \n" "void main() { \n" " float a = gl_FragCoord.x; \n" " int b = int(a); \n" " int d = b % 2; \n" " gl_FragColor.x = 1.0; \n" " gl_FragColor.y = 0.0; \n" " gl_FragColor.z = a * d; \n" " gl_FragColor.w = 0.0; \n" "} \n" ; void CheckGLError(int line) { GLint glErr = glGetError(); if(glErr != GL_NO_ERROR) { printf("OpenGL error %d at line %d\n", glErr, line); exit(1); } } int main() { // Minimal setup. int visual[] = { GLX_RGBA, 0 }; Display *display = XOpenDisplay(NULL); Window window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, 1, 1, 0, 0, 0); XVisualInfo *vInfo = glXChooseVisual(display, DefaultScreen(display), visual); GLXContext glCtx = glXCreateContext(display, vInfo, NULL, 1); glXMakeCurrent(display, window, glCtx); glewInit(); // Build shader program. GLuint vShader = glCreateShader(GL_VERTEX_SHADER); GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER); mChkGL(glShaderSource(vShader, 1, &VertexCode, NULL)); mChkGL(glShaderSource(fShader, 1, &FragmentCode, NULL)); mChkGL(glCompileShader(vShader)); mChkGL(glCompileShader(fShader)); GLint compileLogSize; mChkGL(glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &compileLogSize)); mChkGL(glGetShaderiv(fShader, GL_INFO_LOG_LENGTH, &compileLogSize)); GLuint program = glCreateProgram(); mChkGL(glAttachShader(program, vShader)); mChkGL(glAttachShader(program, fShader)); mChkGL(glLinkProgram(program)); // Bind renderbuffer to capture shader output. GLuint renderBuf; mChkGL(glGenRenderbuffers(1, &renderBuf)); mChkGL(glBindRenderbuffer(GL_RENDERBUFFER, renderBuf)); mChkGL(glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 100, 100)); GLuint frameBuf; mChkGL(glGenFramebuffers(1, &frameBuf)); mChkGL(glBindFramebuffer(GL_FRAMEBUFFER, frameBuf)); mChkGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuf)); mChkGL(glDrawBuffer(GL_COLOR_ATTACHMENT0)); // Render shader across viewport and copy back color output. float vertices[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f }; mChkGL(glEnableClientState(GL_VERTEX_ARRAY)); mChkGL(glVertexPointer(2, GL_FLOAT, 0, vertices)); mChkGL(glUseProgram(program)); mChkGL(glViewport(0, 0, 100, 100)); mChkGL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); float *pixels = new float[100 * 100 * 4]; mChkGL(glReadBuffer(GL_COLOR_ATTACHMENT0)); mChkGL(glReadPixels(0, 0, 100, 100, GL_RGBA, GL_FLOAT, pixels)); // Validate shaded output. for(int y = 0; y < 100; ++ y) { for(int x = 0; x < 100; ++ x) { float *pixel = &pixels[y * 100 * 4 + x * 4]; float expectB = (float(x) + 0.5f) * float(x % 2); if(pixel[0] != 1.0f || pixel[1] != 0.0f || pixel[2] != expectB || pixel[3] != 0.0f) { printf("Validation FAILED\n"); printf(" At %dx%d, expected [1.0,0.0,%.1f,0.0] got [%f,%f,%f,%f]\n", x, y, expectB, pixel[0], pixel[1], pixel[2], pixel[3]); return 1; } } } printf("Validation PASSED\n"); }