参考
http://blog.csdn.net/rootxue/article/details/5399164
http://www.cppblog.com/fwxjj/archive/2011/01/09/138194.html
下图为大家展示了,一对shader(一个顶点shader和一个像素shader)是如何经过编译、连接最后被应用程序所使用的过程。
创建一个Shader
下图像大家展示了编译一个shader对象(类似与生成一个C语言目标文件)的过程。
源代码如下:
sobel.glsl代码
// Sobel edge detection
uniform sampler2D sampler0;
uniform vec2 tc_offset[9];
void main(void)
{
vec4 sample[9];
for (int i = 0; i < 9; i++)
{
sample[i] = texture2D(sampler0,
gl_TexCoord[0].st + tc_offset[i]);
}
// -1 -2 -1 1 0 -1
// H = 0 0 0 V = 2 0 -2
// 1 2 1 1 0 -1
//
// result = sqrt(H^2 + V^2)
vec4 horizEdge = sample[2] + (2.0*sample[5]) + sample[8] -
(sample[0] + (2.0*sample[3]) + sample[6]);
vec4 vertEdge = sample[0] + (2.0*sample[1]) + sample[2] -
(sample[6] + (2.0*sample[7]) + sample[8]);
gl_FragColor.rgb = sqrt((horizEdge.rgb * horizEdge.rgb) +
(vertEdge.rgb * vertEdge.rgb));
gl_FragColor.a = 1.0;
}
template.cpp源代码
#pragma once
#include "stdafx.h"
#include "template.h"
GLuint texture[1]; // Storage For One Texture ( NEW )
int width;
int height;
// Load shader from disk into a null-terminated string
GLubyte *LoadShaderText(const char *fileName)
{
GLubyte *shaderText = NULL;
GLint shaderLength = 0;
FILE *fp;
fp = fopen(fileName, "r");
if (fp != NULL)
{
while (fgetc(fp) != EOF)
{
shaderLength++;
}
rewind(fp);
shaderText = (GLubyte *)malloc(shaderLength+1);
if (shaderText != NULL)
{
fread(shaderText, 1, shaderLength, fp);
}
shaderText[shaderLength] = '\0';
fclose(fp);
}
return shaderText;
}
// Compile shaders
void PrepareShader()
{
glewInit();
int r=glewIsSupported("GL_VERSION_2_0");
GLhandleARB fShader,progObj;
char fullFileName[255];
GLubyte *fsString;
GLcharARB *fsStringPtr[1];
sprintf(fullFileName, "sobel.glsl");
fsString = LoadShaderText(fullFileName);
fShader= glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
fsStringPtr[0] = (GLcharARB *)fsString;
glShaderSourceARB(fShader, 1, (const GLcharARB **)&fsStringPtr, NULL);
free(fsString);
glCompileShaderARB(fShader);
GLint success;
glGetObjectParameterivARB(fShader, GL_OBJECT_COMPILE_STATUS_ARB, &success);
progObj= glCreateProgramObjectARB();
glAttachObjectARB(progObj, fShader);
glLinkProgramARB(progObj);
glGetObjectParameterivARB(progObj, GL_OBJECT_LINK_STATUS_ARB, &success);
GLint uniformLoc;
glUseProgramObjectARB(progObj);
uniformLoc = glGetUniformLocationARB(progObj, "sampler0");
if (uniformLoc != -1)
{
glUniform1iARB(uniformLoc, 0);
}
/*uniformLoc = glGetUniformLocationARB(progObj, "alpha");
if (uniformLoc != -1)
{
glUniform1fARB(uniformLoc,0.5);
}*/
GLfloat texCoordOffsets[18];
GLfloat xInc, yInc;
xInc = 1.0f / (GLfloat)width;
yInc = 1.0f / (GLfloat)height;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
texCoordOffsets[(((i*3)+j)*2)+0] = (-1.0f * xInc) + ((GLfloat)i * xInc);
texCoordOffsets[(((i*3)+j)*2)+1] = (-1.0f * yInc) + ((GLfloat)j * yInc);
}
}
uniformLoc = glGetUniformLocationARB(progObj, "tc_offset");
if (uniformLoc != -1)
{
glUniform2fvARB(uniformLoc, 9, texCoordOffsets);
}
}
AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
{
FILE *File=NULL; // File Handle
if (!Filename) // Make Sure A Filename Was Given
{
return NULL; // If Not Return NULL
}
File=fopen(Filename,"r"); // Check To See If The File Exists
if (File) // Does The File Exist?
{
fclose(File); // Close The Handle
return auxDIBImageLoadA(Filename); // Load The Bitmap And Return A Pointer
}
return NULL; // If Load Failed Return NULL
}
int LoadGLTextures() // Load Bitmaps And Convert To Textures
{
int Status=FALSE; // Status Indicator
AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
if (TextureImage[0]=LoadBMP("Data/256.bmp"))
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[0]); // Create The Texture
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
width=TextureImage[0]->sizeX;
height=TextureImage[0]->sizeY;
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
if (TextureImage[0]) // If Texture Exists
{
if (TextureImage[0]->data) // If Texture Image Exists
{
free(TextureImage[0]->data); // Free The Texture Image Memory
}
free(TextureImage[0]); // Free The Image Structure
}
return Status; // Return The Status
}
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(90.0f,1.0f,0.1f,100.0f);
gluLookAt(0, 0, 1, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
int InitGL(HWND hWnd ) // All Setup For OpenGL Goes Here
{
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
glEnable(GL_TEXTURE_2D);
if (!LoadGLTextures()) // Jump To Texture Loading Routine ( NEW )
{
return FALSE; // If Texture Didn't Load Return FALSE
}
RECT clientrc;
GetClientRect(hWnd,&clientrc);
RECT windowrc;
GetWindowRect(hWnd,&windowrc);
int borderwidth=(windowrc.right-windowrc.left)-(clientrc.right-clientrc.left);
int borderheight=(windowrc.bottom-windowrc.top)-(clientrc.bottom-clientrc.top);
SetWindowPos(hWnd,NULL,0,0,borderwidth+width,borderheight+height,SWP_NOZORDER|SWP_NOMOVE);
PrepareShader();
//glColor4f(1.0f, 1.0f, 1.0f, 0.5); // Full Brightness. 50% Alpha
//glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For Translucency
//glEnable(GL_BLEND);
//glDisable(GL_DEPTH_TEST);
return TRUE; // Initialization Went OK
}
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-0.0f);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
return TRUE;
}
VOID Cleanup()
{
}
//-----------------------------------------------------------------------------
// Desc: 消息处理
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
static POINT ptLastMousePosit;
static POINT ptCurrentMousePosit;
static bool bMousing;
switch( msg )
{
case WM_SIZE: // Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
DrawGLScene();
//SwapBuffers(hDC);
ValidateRect( hWnd, NULL );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Desc: 程序入口
//-----------------------------------------------------------------------------
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX winClass;
MSG uMsg;
memset(&uMsg,0,sizeof(uMsg));
winClass.lpszClassName = L"MY_WINDOWS_CLASS";
winClass.cbSize = sizeof(WNDCLASSEX);
winClass.style = CS_HREDRAW | CS_VREDRAW;
winClass.lpfnWndProc = MsgProc;
winClass.hInstance = hInstance;
winClass.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
winClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winClass.lpszMenuName = NULL;
winClass.cbClsExtra = 0;
winClass.cbWndExtra = 0;
if( !RegisterClassEx(&winClass) )
return E_FAIL;
HWND hWnd = CreateWindowEx( NULL, L"MY_WINDOWS_CLASS",
L"OpenGL - Initialization",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT , CW_USEDEFAULT , NULL, NULL, hInstance, NULL );
SetWindowPos(hWnd,NULL,0,0,640,480,SWP_NOMOVE);
HDC hDC=GetDC(hWnd);
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
16, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
GLuint PixelFormat; // Holds The Results After Searching For A Match
PixelFormat=ChoosePixelFormat(hDC,&pfd);
SetPixelFormat(hDC,PixelFormat,&pfd);
HGLRC hRC=wglCreateContext(hDC);
wglMakeCurrent(hDC,hRC);
RECT clientrc;
GetClientRect(hWnd,&clientrc);
ReSizeGLScene(clientrc.right-clientrc.left, clientrc.bottom-clientrc.top);
//初始化Direct3D
if(SUCCEEDED(InitGL(hWnd)))
{
//if( SUCCEEDED(InitGeometry()))
{
//显示主窗口
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
//进入消息循环
MSG msg;
ZeroMemory( &msg, sizeof(msg) );
while( msg.message!=WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
DrawGLScene(); // Draw The Scene
SwapBuffers(hDC);
}
}
}
}
UnregisterClass( L"ClassName", hInstance);
return 0;
}
![](http://hi.csdn.net/attachment/201110/7/0_1317982501ZwC9.gif)