尝试使用Win32 OpenGL着色器,但顶点着色器不绘制任何内容

时间:2015-10-12 13:02:09

标签: c++ opengl glsl shader

代码粘贴在下面。它什么都没有。 triple是点数组。

program = InitShader("vshader.glsl", "fshader.glsl");
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(triple), triple, GL_STATIC_DRAW);
loc = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_TRUE, 0, BUFFER_OFFSET(0));
glDrawArrays(GL_TRIANGLES, 0, n_triple / 3);

Vertex Shader(vshader.glsl)

#version 400
layout (location = 0) in vec3 vPosition; //In my previous code this varible was named VertexPosition.


void main()
{
    gl_Position = vec4(vPosition, 1.0);
}

但是,如果我只删除顶点着色器的链接并将绘图方法更改为

glVertexPointer(3, GL_FLOAT, 0, triple);

它运作得很好。即使我启用了片段着色器。着色器也可以正常工作。

我只是不知道出了什么问题。

完整代码粘贴在下面:

#include "stdafx.h"
#include <windows.h>
#include <cmath>
#include<cstdlib> 
#include <GL/glew.h>
#include<GL/wglew.h>
#include <GL/glut.h>
#include<iostream>
#include <cstdio>

#define BUFFER_OFFSET( offset )   ((GLvoid*) (offset))
//#pragma comment (lib, "glut32.lib")
using namespace std;
GLuint program, loc;
int w, h;
inline void point3(GLfloat points[], GLfloat x, GLfloat y, GLfloat z, int &i) {
points[i++] = x;
points[i++] = y;
points[i++] = z;
}

inline char* readShaderSource(char* shader)
{

FILE *fp;// = fopen(shader, "r");
fopen_s(&fp, shader, "r");
if (!fp) 
    exit(1);
fseek(fp, 0, SEEK_END);
unsigned long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buf = new char [size+1];
fread_s(buf, size + 1, sizeof(char), size / sizeof(char), fp);
buf[size] = ' ';
fclose(fp);
return buf;
}
GLuint InitShader(char* vertexShader, char* fragmentShader) {
glewInit();
char* vertexSource = readShaderSource(vertexShader), *fragmentSource = readShaderSource(fragmentShader);
GLuint program;
program = glCreateProgram();
GLuint vshader = glCreateShader(GL_VERTEX_SHADER), fshader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vshader, 1, (const GLchar **)&vertexSource, NULL);
glCompileShader(vshader);

glShaderSource(fshader, 1, (const GLchar **) &fragmentSource, NULL);
glCompileShader(fshader);

GLint compiled;
glGetShaderiv(fshader, GL_COMPILE_STATUS, &compiled);
printf("%d", compiled);
GLint length;
glGetShaderiv(fshader, GL_INFO_LOG_LENGTH, &length);
char *msg = new char[length];
glGetShaderInfoLog(fshader, length, NULL, msg);
printf("\n%s\n", msg);
//glAttachShader(program, vshader);
glAttachShader(program, fshader);
GLint linked;
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &linked);
printf("%d", linked);
glUseProgram(program);
return program;
}


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 
int APIENTRY WinMain(HINSTANCE hInstance, 
HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

WCHAR lpszClassName[] = L"Window"; 
WCHAR lpszTitle[] = L"Win32 Project"; 
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0; 
wndclass.cbWndExtra = 0; 
wndclass.hInstance = hInstance; 
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 
wndclass.hbrBackground = NULL; 
wndclass.lpszMenuName = NULL; 
wndclass.lpszClassName = lpszClassName; 
if (!RegisterClass(&wndclass)) 
{
    MessageBeep(0);
    return FALSE;
}

HWND hwnd = CreateWindowW(lpszClassName, lpszTitle, WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
ShowWindow(hwnd, nCmdShow); 
UpdateWindow(hwnd); 

MSG msg; 
while (GetMessage(&msg, NULL, 0, 0)) 
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
return msg.wParam; 
}
void SetupPixelFormat(HDC hDC) 
{
int nPixelFormat; 
static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 
    1, 
    PFD_DRAW_TO_WINDOW | 
    PFD_SUPPORT_OPENGL | 
    PFD_DOUBLEBUFFER, 
    PFD_TYPE_RGBA, 
    32, 
    0, 0, 0, 0, 0, 0, 
    256,
    0, 
    0, 
    0, 0, 0, 0, 
    16, 
    0,
    0, 
    PFD_MAIN_PLANE, 
    0, 
    0, 0, 0 };
pfd.cStencilBits = 8;
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, nPixelFormat, &pfd);
}
int InitGL(GLvoid)                         
{
glShadeModel(GL_SMOOTH);                
glClearColor(0.0f, 255.0f, 244.0f, 244.0f);    
glClearDepth(1.0f);                      
glEnable(GL_DEPTH_TEST);                 
glDepthFunc(GL_LEQUAL);                
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
return TRUE;                            
}
void ChangeSize(int width, int height)
{
glViewport(0, 0, width, height);         
glMatrixMode(GL_PROJECTION);             
glLoadIdentity();                       

gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
w = width;
h = height;
}

void RenderScene()
{
static bool runned = false;
if (!runned)
{
    runned = true;
//#ifdef DEBUG

    FILE* fpDebugOut = NULL;
    FILE* fpDebugIn = NULL;
    if (!AllocConsole()) MessageBox(NULL, _T("Failed to generate console."), NULL, 0);
    SetConsoleTitle(_T("Debug Window"));
    _tfreopen_s(&fpDebugOut, _T("CONOUT$"), _T("w"), stdout);
    _tfreopen_s(&fpDebugIn, _T("CONIN$"), _T("r"), stdin);
//#endif // DEBUG
}

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
glLoadIdentity();     

glTranslatef(-2.0f, -0.0f, -5.0f);  
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnableClientState(GL_VERTEX_ARRAY); 

const GLfloat toradix = 3.14159265358979324 / 180;
int stepper = 2, r = 2, n_triple = 0;
GLfloat *triple = (GLfloat*)malloc(sizeof(GLfloat) * 4000000);//384480

for (int j = -90 + stepper; j < 90 - stepper;j += stepper)
    for (int i = -180; i <= 180;i += stepper)
    {
        point3(triple, r*cos(j*toradix)*sin(i*toradix), r*cos(i*toradix)*cos(j*toradix), r*sin(j*toradix), n_triple);

        j += stepper;
        point3(triple, r*cos(j*toradix)*sin(i*toradix), r*cos(i*toradix)*cos(j*toradix), r*sin(j*toradix), n_triple);

        i += stepper;
        point3(triple, r*cos(j*toradix)*sin(i*toradix), r*cos(i*toradix)*cos(j*toradix), r*sin(j*toradix), n_triple);

        j -= stepper;
        point3(triple, r*cos(j*toradix)*sin(i*toradix), r*cos(i*toradix)*cos(j*toradix), r*sin(j*toradix), n_triple);
    }
program = InitShader("vshader.glsl", "fshader.glsl");
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * n_triple, triple, GL_STATIC_DRAW);
loc = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_TRUE, 0, BUFFER_OFFSET(0));
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, n_triple / 3);
glFlush();

}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
static HGLRC hRC; 
static HDC hDC; 

switch (message) {
case WM_CREATE: {
    hDC = GetDC(hwnd); 
    SetupPixelFormat(hDC); 
    hRC = wglCreateContext(hDC); 
    wglMakeCurrent(hDC, hRC); 
    InitGL();
    return 0;
}
break;
case WM_DESTROY:
{
    wglMakeCurrent(hDC, NULL);
    wglDeleteContext(hRC);
    PostQuitMessage(0); 
}
break;
case WM_SIZE:
{
    ChangeSize(LOWORD(lParam), HIWORD(lParam));
}
break;

case WM_PAINT:
{
    RenderScene();
    SwapBuffers(hDC);
    ValidateRect(hwnd, NULL);
}
break;
default: 
    return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}

1 个答案:

答案 0 :(得分:0)

在OpenGL中,每个顶点属性(以及统一变量)都有其唯一的位置,一种指向该属性的指针。您可以将该位置硬编码为某个值,也可以让OpenGL为您决定。

// Hardcode locations in vertex shader:
layout(location = 0) in vec3 Position; // This attribute will always have the location 0
layout(location = 1) in vec2 TexCoord; // This one will use location 1

// Any location / hardcoded in program:
attribute vec4 Normal;

有关使用顶点属性here的更多信息。

使用&#34;属性&#34;要定义您的顶点属性,您可以使用 glBindAttribLocation 在程序中对其位置进行硬编码(请参阅link)。如果你没有,你就不知道它会占据什么位置。然后,您需要使用 glGetAttribLocation 查询它的位置。

在程序中,您正在搜索名为&#34; vPosition&#34;的顶点属性的位置。在顶点着色器中不存在。在顶点着色器中,您可以定义一个名为&#34; VertexPosition&#34;的属性。并将其分配给位置0.尝试替换&#34; vPosition&#34;使用&#34; VertexPosition&#34;在 glGetAttribLocation 函数中。那样 glGetAttribLocation 应该返回0因为&#34; VertexPosition&#34;被分配到顶点着色器中的该位置,输入应该有效。

您也可以尝试对值进行硬编码&#34; 0&#34;到var&#34; loc&#34;在你的程序中。这样 glEnableVertexAttribArray glVertexAttribPointer 将使用位置&#34; 0&#34;它具有属性&#34; VertexPosition&#34;在顶点着色器中分配给它。