Opengl shader使用チェック

6369 ワード

一、shaderの使用手順
shader 1の作成、shaderオブジェクトの作成
GLuint glCreateShader(GLenum shaderType);  

2.前に作成したshaderオブジェクトにshaderソースコードを入力する
void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lenOfStrings);  

3、shaderのコンパイル
void glCompileShader(GLuint shader); 

shader 1を使用して、プログラムのコンテナとしてオブジェクトを作成します.
GLuint glCreateProgram(void);  

2、作成したばかりのプログラムにコンパイルしたshaderを添付する
void glAttachShader(GLuint program, GLuint shader); 

3、接続プログラム
void glLinkProgram(GLuint program);  

4、使用手順
void glUseProgram(GLuint prog);

シェーダーの削除
void glDeleteShader(GLuint id);  
void glDeleteProgram(GLuint id);

詳細については、
http://blog.csdn.net/racehorse/article/details/6616256
二、shaderデータ型
1、attribute variablesが異なる頂点に従って変化するグローバル変数、すなわち各頂点に対してこの変数を設定することができる.注意:この修飾子は、頂点shaderでのみ使用できます.shaderでは読み取り専用変数です.2、uniformが異なるエンティティに従って変化するグローバル変数、すなわち頂点ごとにこの変数を設定することはできません.注意:glBegin/glEndでは値を設定できません.コンシステント変数は、1つのエンティティ、1つのフレーム、さらには1つのシーンで変わらない値を記述するのに適しています.コンシステント変数は、頂点shaderとセグメントshaderの両方で読み取り専用です.3、varyingは頂点shaderと断片shaderの間で伝達する補間データに用いられ、頂点shaderに書くことができ、断片shaderには読取り専用注:頂点shaderと断片shaderで同時に宣言しなければならない
三、shaderデータ転送
(一)、glsl 2.xデータ転送:
1、attribute変数転送
GLint glGetAttribLocation(GLuint program,char *name); 
void glVertexAttrib1f(GLint location, GLfloat v0);  
void glVertexAttrib2f(GLint location, GLfloat v0, GLfloat v1);  
void glVertexAttrib3f(GLint location, GLfloat v0, GLfloat v1,GLfloat v2);  
void glVertexAttrib4f(GLint location, GLfloat v0, GLfloat v1,,GLfloat v2, GLfloat v3);  

2、uniform変数転送
GLint glGetUniformLocation(GLuint program, const char *name);  
void glUniform1f(GLint location, GLfloat v0);  
void glUniform2f(GLint location, GLfloat v0, GLfloat v1);  
void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);  
void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);  

注意:getlocationはプログラム接続の後、リンク後に自動的に位置が割り当てられるため、必要なときにこの位置を取得(クエリー)できます.
3、varying変数転送
//Vertex Shader  
out vec2 varying_vg_texcoord;    
  
//Geometry Shader  
in  vec2 varying_vg_texcoord[];    
out vec2 varying_gf_texcoord;    
  
//Fragment Shader  
in vec2 varying_gf_texcoord;    

(二)、glsl 3.xデータ転送
GL 3.xではattributeキーワードおよびvaryingキーワードを廃棄し,属性変数はin/outを前置キーワードとして統一する.
各Shaderステージについて、inは入力としての属性であり、outは出力のための属性であることを示す.
1、attribute変数転送
GLSLコードに直接これらの位置値を指定する
#version 330  
layout(location = 0) in vec3 attrib_position; 

ここではlayoutキーワードを使用しています.このキーワードは、特定の変数の前に使用され、その変数のレイアウトプロパティの一部を明示的に示すために使用されます.ここで、attribute変数の位置値(location)が明示的に設定されています.
メリット:
(1)、getlocationのオーバーヘッドを回避した;
(2)、OpenGLとGLSL間のattribute変数属性の依存性を再定義しました.過去のOpenGL側は、GLSL側のattributeの名前を最初に知らなければ位置値を設定/取得できませんでしたが、現在ではlocation対応のみでペイント時の頂点属性ストリームの伝達が完了します
2、uniform変数転送
2.1 UBO
複雑なshaderではuniform変数が多く、glUniform()でデータを伝達すると肥大化する可能性があります.
また,1つのshaderにおけるuniform変数の数は上限があるため,あまりuniform変数を入力することはできない.
以上の理由からUniform Buffer Object(UBO)が提案されており、glUniformの代わりに1つ以上のuniform変数を渡すことができる.
注意:UBOに渡されたデータは、このUBOに格納され、ShaderProgramに渡すのではなく、このShaderProgram自体のuniformストレージスペースを占有しません.
2.2 uniform block
unifomキーワードの後に直接block nameと括弧に従い、中には1つ以上のuniform変数があります.UBOとの関連付けに使用します.
uniform BlobSettings {  
  vec4 InnerColor;  
  vec4 OuterColor;  
  float RadiusInner;  
  float RadiusOuter;  
};  

uniform BlobSettings{  
    vec4 InnerColor;  
    vec4 OuterColor;  
    float RadiusInner;  
    float RadiusOuter;  
}Blob;  
メソッド1では、Blockの変数は依然として全ローカルドメインの一部であり、Block名は使用されません.
メソッド2では、Blockの変数はBlob名ドメインで、使用するときにBlock名を付ける必要があります.
2.3関連
uniform blockごとに「インデックス値」(index)があります.このインデックス値はOpenGLで入手でき、特定のUBOに関連付けることができます.
GLint blockIndex = glGetUniformBlockIndex(nProgramHandler, "BlobSettings"); 
 
GLint nBlockDataSize = 0;  
  
glGetActiveUniformBlockiv(nProgramHandler, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSize);  

glGenBuffers(1, &m_nUBO);  

glBindBuffer(GL_UNIFORM_BUFFER, m_nUBO);  

glBufferData(GL_UNIFORM_BUFFER, nBlockDataSize, NULL, GL_DYNAMIC_DRAW);  

glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_nUBO, 0, nBlockDataSize);  

glUniformBlockBinding(nProgramHandler, blockIndex, 0);  

glBindBuffer(GL_UNIFORM_BUFFER, NULL);  

2.4 Block採用の理由
プログラムに複数のシェーダが含まれており、これらのシェーダが同じUniform変数を使用している場合は、シェーダごとにこれらの変数をそれぞれ管理する必要があります.Uniform変数のlocationはプログラムリンク時に発生するため、Uniform変数のlocationはシェーダによって変化します.したがって、これらのUniform変数のデータは再生成され、新しいlocationに適用される必要があります.
Uniform Blockは、シェーダ間でUniformデータを共有しやすくするために設計されています.Uniform Blockがあれば、これらのUniform変数の値を格納するバッファオブジェクトを作成し、バッファオブジェクトをUniform Blockにバインドできます.シェーダプログラムを変更する場合は、同じバッファペアを新しいシェーダに関連付けられたBlockに再バインドするだけです.
3、varing変数転送
In blockとout blockの2つのvaring変数に使用できる
注意ここではblock insatnce name(括弧に続く名前)を使っていますが、この名前は各Shader Stageにとってユニークなので、上記に変更すると、
block間で名前の衝突も起こらず、block内のvarying変数も同じ名前で使用できます.使用する場合は、「blockInstanceName.varyingVariable」のような構造内変数のスタイルで表示する必要があります.
//Vertex Shader  
out Varying  
{  
     vec2 texcoord;  
}VaryingOut;  
  
//Geometry Shader  
in Varying  
{  
     vec2 texcoord;  
}VaryingIn[];  
  
out Varying  
{  
    vec2 texcoord;  
}VaryingOut;  
  
//Fragment Shader  
in Varying  
{  
    vec2  texcoord;     
}VaryingIn;  

4、fragmentShader出力
上記のattribute変数と同様にlayoutで直接このlocation値を指定することもできます.
/     
layout(location = 0) out vec4 fragColor;  
  
//MRT  
layout(location = 0) out vec4 fragColor0;  
layout(location = 1) out vec4 fragColor1; 

これらのlayoutのキーワードにはindexがあります.デフォルトは0です.
layout(location = 0, index = 0) out vec4 fragColor;  
layout(location = 0, index = 1) out vec4 src1Color; 

参考資料:
http://blog.csdn.net/xiajun07061225/article/details/7709815
http://www.zwqxin.com/archives/shaderglsl/communication-between-opengl-glsl-2.html