固定機能との違い

「固定機能との違い」の編集履歴(バックアップ)一覧はこちら

固定機能との違い」(2014/04/30 (水) 21:12:40) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

<p><strong>固定機能とプログラマブルシェーダーでは何がどう違うのでしょう。<br /> 固定機能ではフラットシェーディングやグーローシェーディング(スムースシェーディング)、<br /> ワイヤーフレーム表示程度しかありませんでした。<br /> 擬似的にトゥーンシェーディングっぽく表示する事もできますが、トゥーンシェーディング<br /> とは全然品質が違います。</strong></p> <p><strong>固定機能というのは、あらかじめ用意された範囲内で簡単手軽に機能を切り替えたり<br /> 描画に関する事を全て 『用意された中から選んで設定する』 という物でした。</strong></p> <p><strong>簡単手軽ですが、グラフィックスで表現できる幅が文字通り固定されています。<br /> そこで、より幅広いグラフィックスを表現するためにプログラマブルシェーダーが登場しました。<br /> ここでは、シェーダー使用の描画とシェーダー未使用の描画をしてみました。<br /> 左が固定機能パイプラインで描画、右がシェーダーで色を反転させて描画した物です。<br /> シェーダーファイルの<br /> gl_Position = gl_ModelViewMatrix * gl_Vertex;//頂点座標の出力<br /> で、gl_ModelViewMatrix を掛け合わせてやらないとモデルビューに行った操作が一切、<br /> 反映されないので注意が必要です。</strong></p> <p> <img alt="" src="http://www21.atwiki.jp/opengl?cmd=upload&amp;act=open&amp;pageid=38&amp;file=shader.png" /></p> <p>シェーダープログラム(vertex.shader)</p> <table border="1" cellspacing="1" cellpadding="1" width="600"><tbody><tr><td><font size="2">void main(void)<br /> {<br />  gl_Position = gl_ModelViewMatrix * gl_Vertex;//頂点座標の出力<br />  gl_FrontColor = vec4(1.0)-gl_Color;//頂点カラーの出力(反転)<br />  //gl_FrontColor = gl_Color;//そのまま出力<br /> }</font></td> </tr></tbody></table><p>メインプログラム(main.cpp)</p> <table border="1" cellspacing="1" cellpadding="1" width="600"><tbody><tr><td> <p><font size="2">#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br /> #pragma comment(lib, "glew32.lib")<br /> #include &lt;stdio.h&gt;<br /> #include &lt;GL/glew.h&gt;<br /> #include &lt;GL/freeglut/freeglut.h&gt;</font></p> <p><font size="2">#define WIDTH 320<br /> #define HEIGHT 240</font></p> <p><font size="2">GLuint shaderProg;</font></p> <p><font size="2">GLuint vertexShader, fragmentShader;<br /> //shader fileを読み込みコンパイルする<br /> void readShaderCompile(GLuint shader, const char *file)<br /> {<br />   FILE *fp;<br />   char *buf;<br />   GLsizei size, len;<br />   GLint compiled;<br />  <br />   // ファイルを開く<br />   fopen_s(&amp;fp,file, "rb");<br />   if(!fp) printf("ファイルを開くことができません %s\n", file);<br />  <br />   //ファイルの末尾に移動し現在位置を得る<br />   fseek(fp, 0, SEEK_END);<br />   size = ftell(fp);//ファイルサイズを取得<br />  <br />   // ファイルサイズのメモリを確保<br />   buf = (GLchar *)malloc(size);<br />   if (buf == NULL) {<br />     printf("メモリが確保できませんでした \n");<br />   }<br />  <br />   // ファイルを先頭から読み込む<br />   fseek(fp, 0, SEEK_SET);<br />   fread(buf, 1, size, fp);<br />   //シェーダオブジェクトにプログラムをセット<br />   glShaderSource(shader, 1, (const GLchar **)&amp;buf, &amp;size);<br />   //シェーダ読み込み領域の解放<br />   free(buf);<br />   fclose(fp);</font></p> <p><font size="2">  // シェーダのコンパイル<br />   glCompileShader(shader);<br />   glGetShaderiv( shader, GL_COMPILE_STATUS, &amp;compiled );</font></p> <p><font size="2">  if ( compiled == GL_FALSE )<br />   {<br />    printf( "コンパイルできませんでした!!: %s \n ", file);<br />    glGetProgramiv( shader, GL_INFO_LOG_LENGTH, &amp;size );<br />    if ( size &gt; 0 )<br />    {<br />     buf = (char *)malloc(size);<br />     glGetShaderInfoLog( shader, size, &amp;len, buf);<br />     printf(buf);<br />     free(buf);<br />    }<br />   }<br /> }</font></p> <p><font size="2">//リンクする<br /> void link( GLuint prog )<br /> {<br />   GLsizei size, len;<br />   GLint linked;<br />   char *infoLog ;</font></p> <p><font size="2">  glLinkProgram( prog );</font></p> <p><font size="2">  glGetProgramiv( prog, GL_LINK_STATUS, &amp;linked );</font></p> <p><font size="2">  if ( linked == GL_FALSE )<br />   {<br />   printf("リンクできませんでした!! \n");<br />     <br />   glGetProgramiv( prog, GL_INFO_LOG_LENGTH, &amp;size );<br />   if ( size &gt; 0 )<br />   {<br />    infoLog = (char *)malloc(size);<br />    glGetProgramInfoLog( prog, size, &amp;len, infoLog );<br />    printf(infoLog);<br />    free(infoLog);<br />   }<br />   }<br /> }<br /> //GLSLの初期化<br /> void initGlsl(GLuint *program, const char *vertexFile)<br /> {<br />   //glewの初期化<br />   GLenum err = glewInit();<br />   if (err != GLEW_OK)<br />   {<br />    printf("Error: %s\n", glewGetErrorString(err));<br />   }<br />   // GPU,OpenGL情報<br />   printf("VENDOR= %s \n", glGetString(GL_VENDOR));<br />   printf("GPU= %s \n", glGetString(GL_RENDERER));<br />   printf("OpenGL= %s \n", glGetString(GL_VERSION));<br />   printf("GLSL= %s \n", glGetString(GL_SHADING_LANGUAGE_VERSION));<br />   //シェーダーオブジェクトの作成<br />   vertexShader = glCreateShader(GL_VERTEX_SHADER);<br />   //シェーダーの読み込みとコンパイル<br />   readShaderCompile(vertexShader, vertexFile);</font></p> <p><font size="2">  // シェーダプログラムの作成<br />   *program = glCreateProgram();</font></p> <p><font size="2">  // シェーダオブジェクトをシェーダプログラムに関連付ける<br />   glAttachShader(*program, vertexShader);</font></p> <p><font size="2">  // シェーダオブジェクトの削除<br />   glDeleteShader(vertexShader);</font></p> <p><font size="2">  // シェーダプログラムのリンク<br />   link(*program);<br /> }</font></p> <p><br /><font size="2">void initGlsl(GLuint *program, const char *vertexFile, const char *fragmentFile)<br /> {<br />   //glewの初期化<br />   GLenum err = glewInit();<br />   if (err != GLEW_OK)<br />   {<br />    printf("Error: %s\n", glewGetErrorString(err));<br />   }<br />   // GPU,OpenGL情報<br />   printf("VENDOR= %s \n", glGetString(GL_VENDOR));<br />   printf("GPU= %s \n", glGetString(GL_RENDERER));<br />   printf("OpenGL= %s \n", glGetString(GL_VERSION));<br />   printf("GLSL= %s \n", glGetString(GL_SHADING_LANGUAGE_VERSION));<br />   //シェーダーオブジェクトの作成<br />   vertexShader = glCreateShader(GL_VERTEX_SHADER);<br />   fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);<br />   //シェーダーの読み込みとコンパイル<br />   readShaderCompile(vertexShader, vertexFile);<br />   readShaderCompile(fragmentShader, fragmentFile);</font></p> <p><font size="2">  // プログラムオブジェクトの作成<br />   *program = glCreateProgram();</font></p> <p><font size="2">  // シェーダオブジェクトをシェーダプログラムに関連付ける<br />   glAttachShader(*program, vertexShader);<br />   glAttachShader(*program, fragmentShader);</font></p> <p><font size="2">  // シェーダオブジェクトの削除<br />   glDeleteShader(vertexShader);<br />   glDeleteShader(fragmentShader);<br />   // シェーダプログラムのリンク<br />   link(*program);<br /> }</font></p> <p><br /><font size="2">void Triangle(int x,int y,int size,float linesize){<br />  glLineWidth(linesize);<br />  //モード<br />  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);<br />  glBegin(GL_TRIANGLES);<br />  glColor4f(1.0f,0.0f,0.0f,1.0f);glVertex2i(x-size/2,y+size/2);<br />  glColor4f(0.0f,1.0f,0.0f,1.0f);glVertex2i(x,y-size/2);<br />  glColor4f(0.0f,0.0f,1.0f,1.0f);glVertex2i(x+size/2,y+size/2);<br />  glEnd();<br /> }<br /> void display(void)<br /> {<br />  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />  Triangle(90,100,100,10);//固定機能で描画<br />  glUseProgram(shaderProg);//シェーダー描画に切り替え<br />  Triangle(230,100,100,10);//シェーダーで描画<br />  glUseProgram(0);//シェーダー解除</font></p> <p><font size="2"> glutSwapBuffers();<br /> }<br /> void idle(void)<br /> {<br />  glutPostRedisplay();<br /> }<br /> void Init(){<br />  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);<br />  glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);<br /> }<br /> int main(int argc, char *argv[])<br /> {<br />  glutInitWindowPosition(100, 100);<br />  glutInitWindowSize(WIDTH, HEIGHT);<br />  glutInit(&amp;argc, argv);<br />  glutCreateWindow("固定機能とシェーダーで描画");<br />  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />  glutDisplayFunc(display);<br />  glutIdleFunc(idle);<br />  initGlsl(&amp;shaderProg, "vertex.shader");<br />  Init();<br />  glutMainLoop();<br />  glDeleteProgram(shaderProg);<br />  return 0;<br /> }</font></p> </td> </tr></tbody></table><p> </p> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p>
<p><strong>固定機能とプログラマブルシェーダーでは何がどう違うのでしょう。<br /> 固定機能ではフラットシェーディングやグーローシェーディング(スムースシェーディング)、<br /> ワイヤーフレーム表示程度しかありませんでした。<br /> 擬似的にトゥーンシェーディングっぽく表示する事もできますが、トゥーンシェーディング<br /> とは全然品質が違います。</strong></p> <p><strong>固定機能というのは、あらかじめ用意された範囲内で簡単手軽に機能を切り替えたり<br /> 描画に関する事を全て 『用意された中から選んで設定する』 という物でした。</strong></p> <p><strong>簡単手軽ですが、グラフィックスで表現できる幅が文字通り固定されています。<br /> そこで、より幅広いグラフィックスを表現するためにプログラマブルシェーダーが登場しました。<br /> ここでは、シェーダー使用の描画とシェーダー未使用の描画をしてみました。<br /> 左が固定機能パイプラインで描画、右がシェーダーで色を反転させて描画した物です。<br /> シェーダーファイルの<br /> gl_Position = gl_ModelViewMatrix * gl_Vertex;//頂点座標の出力<br /> で、gl_ModelViewMatrix を掛け合わせてやらないとモデルビューに行った操作が一切、<br /> 反映されないので注意が必要です。</strong></p> <p> <img alt="" src="http://cdn21.atwikiimg.com/opengl?cmd=upload&amp;act=open&amp;pageid=38&amp;file=shader.png" /></p> <p>シェーダープログラム(vertex.shader)</p> <table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td><font size="2">void main(void)<br /> {<br />  gl_Position = gl_ModelViewMatrix * gl_Vertex;//頂点座標の出力<br />  gl_FrontColor = vec4(1.0)-gl_Color;//頂点カラーの出力(反転)<br />  //gl_FrontColor = gl_Color;//そのまま出力<br /> }</font></td> </tr></tbody></table><p>メインプログラム(main.cpp)</p> <table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td> <p>#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br /> #pragma comment(lib, "glew32.lib")<br /> #include &lt;stdio.h&gt;<br /> #include &lt;GL/glew.h&gt;<br /> #include &lt;GL/freeglut/freeglut.h&gt;</p> <p>#define WIDTH 320<br /> #define HEIGHT 240</p> <p>GLuint shaderProg;</p> <p>GLuint vertexShader, fragmentShader;<br /> //shader fileを読み込みコンパイルする<br /> void readShaderCompile(GLuint shader, const char *file){<br />   FILE *fp;<br />   char *buf;<br />   GLsizei size, len;<br />   GLint compiled;<br />   // ファイルを開く<br />   fopen_s(&amp;fp,file, "rb");<br />   if(!fp) printf("ファイルを開くことができません %s\n", file);<br />   //ファイルの末尾に移動し現在位置を得る<br />   fseek(fp, 0, SEEK_END);<br />   size = ftell(fp);//ファイルサイズを取得<br />   // ファイルサイズのメモリを確保<br />   buf = (GLchar *)malloc(size);<br />   if(buf == NULL){<br />     printf("メモリが確保できませんでした \n");<br />   }<br />   // ファイルを先頭から読み込む<br />   fseek(fp, 0, SEEK_SET);<br />   fread(buf, 1, size, fp);<br />   //シェーダオブジェクトにプログラムをセット<br />   glShaderSource(shader, 1, (const GLchar **)&amp;buf, &amp;size);<br />   //シェーダ読み込み領域の解放<br />   free(buf);<br />   fclose(fp);<br />   // シェーダのコンパイル<br />   glCompileShader(shader);<br />   glGetShaderiv( shader, GL_COMPILE_STATUS, &amp;compiled );<br />   if( compiled == GL_FALSE ){<br />    printf( "コンパイルできませんでした!!: %s \n ", file);<br />    glGetProgramiv( shader, GL_INFO_LOG_LENGTH, &amp;size );<br />    if( size &gt; 0 ){<br />     buf = (char *)malloc(size);<br />     glGetShaderInfoLog( shader, size, &amp;len, buf);<br />     printf(buf);<br />     free(buf);<br />    }<br />   }<br /> }</p> <p>//リンクする<br /> void link( GLuint prog ){<br />   GLsizei size, len;<br />   GLint linked;<br />   char *infoLog ;<br />   glLinkProgram( prog );<br />   glGetProgramiv( prog, GL_LINK_STATUS, &amp;linked );<br />   if( linked == GL_FALSE ){<br />   printf("リンクできませんでした!! \n");<br />   glGetProgramiv( prog, GL_INFO_LOG_LENGTH, &amp;size );<br />   if( size &gt; 0 ){<br />    infoLog = (char *)malloc(size);<br />    glGetProgramInfoLog( prog, size, &amp;len, infoLog );<br />    printf(infoLog);<br />    free(infoLog);<br />   }<br />   }<br /> }<br /> //GLSLの初期化<br /> void initGlsl(GLuint *program, const char *vertexFile){<br />   //glewの初期化<br />   GLenum err = glewInit();<br />   if (err != GLEW_OK){<br />    printf("Error: %s\n", glewGetErrorString(err));<br />   }<br />   // GPU,OpenGL情報<br />   printf("VENDOR= %s \n", glGetString(GL_VENDOR));<br />   printf("GPU= %s \n", glGetString(GL_RENDERER));<br />   printf("OpenGL= %s \n", glGetString(GL_VERSION));<br />   printf("GLSL= %s \n", glGetString(GL_SHADING_LANGUAGE_VERSION));<br />   //シェーダーオブジェクトの作成<br />   vertexShader = glCreateShader(GL_VERTEX_SHADER);<br />   //シェーダーの読み込みとコンパイル<br />   readShaderCompile(vertexShader, vertexFile);<br />   // シェーダプログラムの作成<br />   *program = glCreateProgram();<br />   // シェーダオブジェクトをシェーダプログラムに関連付ける<br />   glAttachShader(*program, vertexShader);<br />   // シェーダオブジェクトの削除<br />   glDeleteShader(vertexShader);<br />   // シェーダプログラムのリンク<br />   link(*program);<br /> }</p> <p><br /> void initGlsl(GLuint *program, const char *vertexFile, const char *fragmentFile){<br />   //glewの初期化<br />   GLenum err = glewInit();<br />   if (err != GLEW_OK){<br />    printf("Error: %s\n", glewGetErrorString(err));<br />   }<br />   // GPU,OpenGL情報<br />   printf("VENDOR= %s \n", glGetString(GL_VENDOR));<br />   printf("GPU= %s \n", glGetString(GL_RENDERER));<br />   printf("OpenGL= %s \n", glGetString(GL_VERSION));<br />   printf("GLSL= %s \n", glGetString(GL_SHADING_LANGUAGE_VERSION));<br />   //シェーダーオブジェクトの作成<br />   vertexShader = glCreateShader(GL_VERTEX_SHADER);<br />   fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);<br />   //シェーダーの読み込みとコンパイル<br />   readShaderCompile(vertexShader, vertexFile);<br />   readShaderCompile(fragmentShader, fragmentFile);<br />   // プログラムオブジェクトの作成<br />   *program = glCreateProgram();<br />   // シェーダオブジェクトをシェーダプログラムに関連付ける<br />   glAttachShader(*program, vertexShader);<br />   glAttachShader(*program, fragmentShader);<br />   // シェーダオブジェクトの削除<br />   glDeleteShader(vertexShader);<br />   glDeleteShader(fragmentShader);<br />   // シェーダプログラムのリンク<br />   link(*program);<br /> }</p> <p>void Triangle(int x,int y,int size,float linesize){<br />  glLineWidth(linesize);<br />  //モード<br />  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);<br />  glBegin(GL_TRIANGLES);<br />  glColor4f(1.0f,0.0f,0.0f,1.0f);glVertex2i(x-size/2,y+size/2);<br />  glColor4f(0.0f,1.0f,0.0f,1.0f);glVertex2i(x,y-size/2);<br />  glColor4f(0.0f,0.0f,1.0f,1.0f);glVertex2i(x+size/2,y+size/2);<br />  glEnd();<br /> }<br /> void display(void){<br />  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />  Triangle(90,100,100,10);//固定機能で描画<br />  glUseProgram(shaderProg);//シェーダー描画に切り替え<br />  Triangle(230,100,100,10);//シェーダーで描画<br />  glUseProgram(0);//シェーダー解除<br />  glutSwapBuffers();<br /> }<br /> void idle(void){<br />  glutPostRedisplay();<br /> }<br /> void Init(){<br />  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);<br />  glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);<br /> }<br /> void main(int argc, char *argv[]){<br />  glutInitWindowPosition(100, 100);<br />  glutInitWindowSize(WIDTH, HEIGHT);<br />  glutInit(&amp;argc, argv);<br />  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />  glutCreateWindow("固定機能とシェーダーで描画");<br />  glutDisplayFunc(display);<br />  glutIdleFunc(idle);<br />  initGlsl(&amp;shaderProg, "vertex.shader");<br />  Init();<br />  glutMainLoop();<br />  glDeleteProgram(shaderProg);<br />  return;<br /> }</p> </td> </tr></tbody></table><p> </p> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p>

表示オプション

横に並べて表示:
変化行の前後のみ表示: