since: 2012/06/07
update: 2012/06/07
reference:
1. OpenGL ES 2.0 for iPhone Tutorial | Ray Wenderlich
2. I touchs: OpenGL ES 2.0 Tutorial Part 1 - 1
3. I touchs: OpenGL ES 2.0 Tutorial Part 1 - 2
Compiling Vertex and Fragment Shaders
A. 說明:
1. 接下來要做的工作是: 讓應用程式在執行時, 能即時地編譯這些 shaders 以供使用.
2. 經由這樣的設置方式, shader code 才不會只相依於某些特定的繪圖晶片.
----------------------------------------------------------------------------------
B. 開啟 OpenGLView.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
#import <QuartzCore/QuartzCore.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
@interface OpenGLView : UIView
{
//@add
CAEAGLLayer *_eaglLayer;
EAGLContext *_context;
GLuint _colorRenderBuffer;
//@add
GLuint _positionSlot;
GLuint _colorSlot;
}
//@add
- (void)setupLayer; // Set layer to opaque(不透明)
- (void)setupContext; // Create OpenGL context
- (void)setupRenderBuffer; // Create a render buffer
- (void)setupFrameBuffer; // Create a frame buffer
- (void)render; // render something
//@add
- (GLuint)compileShader:(NSString *)shaderName withType:(GLenum)shaderType;
- (void)compileShaders;
@end
----------------------------------------------------------------------------------
C. 開啟 OpenGLView.m 檔案, 修改如下:
....
//@add
- (GLuint)compileShader:(NSString *)shaderName withType:(GLenum)shaderType
{
// 1. Gets an NSString with the contents of the file.
NSString *shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:@"glsl"];
NSError *error;
NSString *shaderString = [NSString stringWithContentsOfFile:shaderPath
encoding:NSUTF8StringEncoding error:&error];
if (!shaderString) {
NSLog(@"Error loading shader: %@", error.localizedDescription);
exit(1);
}
// 2. Create a OpenGL object to represent the shader
GLuint shaderHandle = glCreateShader(shaderType);
// 3.1
// Convert the source code from an NSString to a C-string
const char *shaderStringUTF8 = [shaderString UTF8String];
int shaderStringLength = [shaderString length];
// 3.2
// Give OpenGL the source code for this shader.
glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);
// 4. Compile the shader at runtime
glCompileShader(shaderHandle);
// 5. Error handle
GLint compileSuccess;
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
// If fail, output any error messages to the screen & quit app
if (compileSuccess == GL_FALSE) {
GLchar messages[256];
glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
NSString *messageString = [NSString stringWithUTF8String:messages];
NSLog(@"%@", messageString);
exit(1);
}
return shaderHandle;
}
....
//@add
- (void)compileShaders
{
// 1. Compile the vertex and fragment shaders.
GLuint vertexShader = [self compileShader:@"SimpleVertex" withType:GL_VERTEX_SHADER];
GLuint fragmentShader = [self compileShader:@"SimpleFragment" withType:GL_FRAGMENT_SHADER];
// 2. Link the vertex and fragment shaders into a complete program.
GLuint programHandle = glCreateProgram();
glAttachShader(programHandle, vertexShader);
glAttachShader(programHandle, fragmentShader);
glLinkProgram(programHandle);
// 3. Check and see if there were any link errors,
// and display the output and quit if so.
GLint linkSuccess;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
if (linkSuccess == GL_FALSE) {
GLchar messages[256];
glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
NSString *messageString = [NSString stringWithUTF8String:messages];
NSLog(@"%@", messageString);
exit(1);
}
// 4. Tell OpenGL to actually use this program when given vertex info.
glUseProgram(programHandle);
// 5-1. Get a pointer to the input values for the vertex shader,
// so we can set them in code.
_positionSlot = glGetAttribLocation(programHandle, "Position");
_colorSlot = glGetAttribLocation(programHandle, "SourceColor");
// 備註: 此處可取得 vertex shader "Position" 與 "SourceColor" 變數的指標
// 5-2. Enable use of these arrays (they are disabled by default).
glEnableVertexAttribArray(_positionSlot);
glEnableVertexAttribArray(_colorSlot);
}
....
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//@add
[self setupLayer]; // Set layer to opaque(不透明)
[self setupContext]; // Create OpenGL context
[self setupRenderBuffer]; // Create a render buffer
[self setupFrameBuffer]; // Create a frame buffer
//@add
[self compileShaders];
[self render]; // render something
}
return self;
}
....
----------------------------------------------------------------------------------
D. 編譯並執行:
說明: 如果執行時仍然是顯示綠色的螢幕, 並且沒有因錯誤而離開應用程式,
就代表 vertex 與 fragment shaders 在執行時編譯成功.
結果: 實際上編譯後執行, 出現錯誤訊息如下:
ERROR: 0:22: 'premature EOF' : syntax error syntax error
原因: 應該是讀到錯誤的字元, 導致讀檔的動作提前結束.
解決: 移除 shaders 裡所有的中文字, 包含在註解裡面的.
(實際上, 我把所有的註解都移除了, 下次記得 shaders 裡的註解要用英文 )
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。