「鏡面反射」の編集履歴(バックアップ)一覧はこちら
「鏡面反射」(2014/05/01 (木) 17:54:26) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
<p><strong>プラスチックや金属など、よく磨きこまれた反射率の高い物体に光が当たると<br />
表面が光り輝いているように見えます。<br />
そのハイライトを表現するのが鏡面反射です。</strong></p>
<p> <img alt="" src="http://www21.atwiki.jp/opengl?cmd=upload&act=open&pageid=48&file=specular.png" /></p>
<p>vertex.shader</p>
<table border="1" cellspacing="1" cellpadding="1" width="600"><tbody><tr><td>
<p><font size="2">//フラグメントシェーダーに渡す変数<br />
varying vec3 P;//位置ベクトル<br />
varying vec3 N;//法線ベクトル</font></p>
<p><font size="2">void main(void)<br />
{<br />
P = vec3(gl_ModelViewMatrix * gl_Vertex);<br />
N = normalize(gl_NormalMatrix * gl_Normal);<br />
gl_Position = ftransform();<br />
}</font></p>
</td>
</tr></tbody></table><p>flagment.shader</p>
<table border="1" cellspacing="1" cellpadding="1" width="600"><tbody><tr><td>
<p><font size="2">//頂点シェーダーから受け取る変数<br />
varying vec3 P;//位置ベクトル<br />
varying vec3 N;//法線ベクトル</font></p>
<p><font size="2">void main(void)<br />
{<br />
vec3 L = normalize(gl_LightSource[0].position.xyz - P);<br />
N = normalize(N);<br />
<br />
vec4 ambient = gl_FrontLightProduct[0].ambient;<br />
float dotNL = dot(N, L);<br />
vec4 diffuse = gl_FrontLightProduct[0].diffuse * max(0.0, dotNL);<br />
vec3 V = normalize(-P);<br />
vec3 H = normalize(L + V);<br />
float powNH = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);<br />
if(dotNL <= 0.0) powNH = 0.0;<br />
vec4 specular = gl_FrontLightProduct[0].specular * powNH;<br />
//統合<br />
gl_FragColor = ambient + diffuse + specular;<br />
}</font></p>
</td>
</tr></tbody></table><p>GLSL.h</p>
<table border="1" cellspacing="1" cellpadding="1" width="600"><tbody><tr><td>
<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(&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 **)&buf, &size);<br />
//シェーダ読み込み領域の解放<br />
free(buf);<br />
fclose(fp);</font></p>
<p><font size="2"> // シェーダのコンパイル<br />
glCompileShader(shader);<br />
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );</font></p>
<p><font size="2"> if ( compiled == GL_FALSE )<br />
{<br />
printf( "コンパイルできませんでした!!: %s \n ", file);<br />
glGetProgramiv( shader, GL_INFO_LOG_LENGTH, &size );<br />
if ( size > 0 )<br />
{<br />
buf = (char *)malloc(size);<br />
glGetShaderInfoLog( shader, size, &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, &linked
);</font></p>
<p><font size="2"> if ( linked == GL_FALSE )<br />
{<br />
printf("リンクできませんでした!! \n");<br />
<br />
glGetProgramiv( prog, GL_INFO_LOG_LENGTH, &size );<br />
if ( size > 0 )<br />
{<br />
infoLog = (char *)malloc(size);<br />
glGetProgramInfoLog( prog, size, &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 />
}<br /></font></p>
</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")</font></p>
<p><font size="2">#include <stdio.h><br />
#include <GL/glew.h><br />
#include <GL/freeglut/freeglut.h><br />
#include "GLSL.h"</font></p>
<p><font size="2">#define WIDTH 320<br />
#define HEIGHT 240</font></p>
<p><font size="2">GLuint shaderProg;<br />
//回転用<br />
float anglex = 0.0f;<br />
//ライトの位置<br />
GLfloat lightpos[] = { 20.0, 80.0, -50.0, 1.0 };</font></p>
<p><font size="2">float Ambient[] = {0.8f, 0.0f, 0.2f, 1.0f};<br />
float Diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};<br />
float specular[]= { 0.4, 0.4, 0.4, 1.0};//鏡面反射<br />
float AmbientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f};<br />
float DiffuseLight[] = { 0.2f, 0.7f, 0.7f, 1.0f};<br />
float SpecularLight[] = {1.0, 1.0, 1.0, 1.0};//鏡面光</font></p>
<p><br /><font size="2">void setLight()<br />
{<br />
glMaterialfv(GL_FRONT,GL_AMBIENT,Ambient);<br />
glMaterialfv(GL_FRONT,GL_DIFFUSE,Diffuse);<br />
glMaterialfv(GL_FRONT,GL_SPECULAR,specular);<br />
glMaterialf(GL_FRONT,GL_SHININESS,8);<br />
glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientLight);<br />
glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);<br />
glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularLight);<br />
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);<br />
}<br />
void display(void)<br />
{</font></p>
<p><font size="2"> glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />
glViewport(0, 0, WIDTH, HEIGHT);<br />
glMatrixMode(GL_PROJECTION);<br />
glLoadIdentity();<br />
//視野角,アスペクト比(ウィンドウの幅/高さ),描画する範囲(最も近い距離,最も遠い距離)<br />
gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 1000.0);<br />
glMatrixMode(GL_MODELVIEW);<br />
glLoadIdentity();<br />
//視点の設定<br />
gluLookAt(150.0,100.0,-200.0, //カメラの座標<br />
0.0,0.0,0.0, // 注視点の座標<br />
0.0,1.0,0.0); // 画面の上方向を指すベクトル<br />
//ライトの設定<br />
setLight();</font></p>
<p><font size="2"> //回転<br />
glRotatef(anglex,1.0f,0.0f,0.0f);//X軸を回転<br />
glUseProgram(shaderProg);//シェーダー描画に切り替え<br />
glutSolidSphere(40.0,16,16);<br />
glUseProgram(0);//シェーダー解除</font></p>
<p><font size="2"> glutSwapBuffers();<br />
}<br />
void idle(void)<br />
{<br />
anglex+=0.02f;</font></p>
<p><font size="2"> glutPostRedisplay();<br />
}<br />
void Init(){<br />
initGlsl(&shaderProg, "vertex.shader","flagment.shader");<br />
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);<br />
glEnable(GL_DEPTH_TEST);<br />
glEnable(GL_LIGHTING);<br />
glEnable(GL_LIGHT0);</font></p>
<p><font size="2">}<br />
int main(int argc, char *argv[])<br />
{<br />
glutInitWindowPosition(100, 100);<br />
glutInitWindowSize(WIDTH, HEIGHT);<br />
glutInit(&argc, argv);<br />
glutCreateWindow("スペキュラー");<br />
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />
glutDisplayFunc(display);<br />
glutIdleFunc(idle);<br />
Init();<br />
glutMainLoop();<br />
glDeleteProgram(shaderProg);<br />
return 0;<br />
}<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 />
そのハイライトを表現するのが鏡面反射です。</strong></p>
<p> <img alt="" src="http://cdn21.atwikiimg.com/opengl?cmd=upload&act=open&pageid=48&file=specular.png" /></p>
<p>vertex.shader</p>
<table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td>
<p><font size="2">//フラグメントシェーダーに渡す変数<br />
varying vec3 P;//位置ベクトル<br />
varying vec3 N;//法線ベクトル</font></p>
<p><font size="2">void main(void)<br />
{<br />
P = vec3(gl_ModelViewMatrix * gl_Vertex);<br />
N = normalize(gl_NormalMatrix * gl_Normal);<br />
gl_Position = ftransform();<br />
}</font></p>
</td>
</tr></tbody></table><p>flagment.shader</p>
<table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td>
<p><font size="2">//頂点シェーダーから受け取る変数<br />
varying vec3 P;//位置ベクトル<br />
varying vec3 N;//法線ベクトル</font></p>
<p><font size="2">void main(void)<br />
{<br />
vec3 L = normalize(gl_LightSource[0].position.xyz - P);<br />
N = normalize(N);<br />
<br />
vec4 ambient = gl_FrontLightProduct[0].ambient;<br />
float dotNL = dot(N, L);<br />
vec4 diffuse = gl_FrontLightProduct[0].diffuse * max(0.0, dotNL);<br />
vec3 V = normalize(-P);<br />
vec3 H = normalize(L + V);<br />
float powNH = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);<br />
if(dotNL <= 0.0) powNH = 0.0;<br />
vec4 specular = gl_FrontLightProduct[0].specular * powNH;<br />
//統合<br />
gl_FragColor = ambient + diffuse + specular;<br />
}</font></p>
</td>
</tr></tbody></table><p>GLSL.h</p>
<table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td>
<p>#pragma once<br />
#include <stdio.h><br />
<br />
//GLSLクラス<br />
class GLSL{<br />
public:<br />
GLuint ShaderProg;<br />
GLuint VertexShader, FragmentShader;<br />
void ReadShaderCompile(GLuint Shader, const char *File);//shader
fileを読み込みコンパイルする<br />
void Link( GLuint Prog );//リンクする<br />
void InitGLSL(const char *VertexFile);//GLSLの初期化<br />
void InitGLSL(const char *VertexFile, const char
*FragmentFile);//GLSLの初期化<br />
void ON();//シェーダー描画に切り替え<br />
void OFF();//シェーダー解除<br />
~GLSL();<br />
};<br />
<br />
void GLSL::ReadShaderCompile(GLuint Shader, const char *File){<br />
FILE *fp;<br />
char *buf;<br />
GLsizei size, len;<br />
GLint compiled;<br />
<br />
fopen_s(&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 />
glShaderSource(Shader, 1, (const GLchar **)&buf, &size);<br />
free(buf);<br />
fclose(fp);<br />
<br />
glCompileShader(Shader);<br />
glGetShaderiv( Shader, GL_COMPILE_STATUS, &compiled );<br />
<br />
if ( compiled == GL_FALSE )<br />
{<br />
printf( "コンパイルできませんでした!!: %s \n ", File);<br />
glGetProgramiv( Shader, GL_INFO_LOG_LENGTH, &size );<br />
if ( size > 0 )<br />
{<br />
buf = (char *)malloc(size);<br />
glGetShaderInfoLog( Shader, size, &len, buf);<br />
printf(buf);<br />
free(buf);<br />
}<br />
}<br />
}<br />
<br />
void GLSL::Link( GLuint Prog ){<br />
GLsizei size, len;<br />
GLint linked;<br />
char *infoLog ;<br />
<br />
glLinkProgram( Prog );<br />
<br />
glGetProgramiv( Prog, GL_LINK_STATUS, &linked );<br />
<br />
if ( linked == GL_FALSE ){<br />
printf("リンクできませんでした!! \n");<br />
<br />
glGetProgramiv( Prog, GL_INFO_LOG_LENGTH, &size );<br />
if ( size > 0 ){<br />
infoLog = (char *)malloc(size);<br />
glGetProgramInfoLog( Prog, size, &len, infoLog );<br />
printf(infoLog);<br />
free(infoLog);<br />
}<br />
}<br />
}<br />
<br />
void GLSL::InitGLSL(const char *VertexFile){<br />
GLenum err = glewInit();<br />
if (err != GLEW_OK)<br />
{<br />
printf("Error: %s\n", glewGetErrorString(err));<br />
}<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 />
VertexShader = glCreateShader(GL_VERTEX_SHADER);<br />
ReadShaderCompile(VertexShader, VertexFile);<br />
ShaderProg = glCreateProgram();<br />
glAttachShader(ShaderProg, VertexShader);<br />
glDeleteShader(VertexShader);<br />
Link(ShaderProg);<br />
}<br />
<br />
<br />
void GLSL::InitGLSL(const char *VertexFile, const char *FragmentFile){<br />
GLenum err = glewInit();<br />
if (err != GLEW_OK)<br />
{<br />
printf("Error: %s\n", glewGetErrorString(err));<br />
}<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 />
ShaderProg = glCreateProgram();<br />
<br />
glAttachShader(ShaderProg, VertexShader);<br />
glAttachShader(ShaderProg, FragmentShader);<br />
<br />
glDeleteShader(VertexShader);<br />
glDeleteShader(FragmentShader);<br />
Link(ShaderProg);<br />
}<br />
<br />
void GLSL::ON(){<br />
glUseProgram(ShaderProg);<br />
}<br />
<br />
void GLSL::OFF(){<br />
glUseProgram(0);<br />
}<br />
<br />
GLSL::~GLSL(){<br />
glDeleteProgram(ShaderProg);<br />
}<br />
</p>
<p> </p>
</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")</p>
<p>#include <stdio.h><br />
#include <GL/glew.h><br />
#include <GL/freeglut/freeglut.h><br />
#include "GLSL.h"</p>
<p>#define WIDTH 320<br />
#define HEIGHT 240</p>
<p>GLSL glsl;<br />
//回転用<br />
float anglex = 0.0f;<br />
//ライトの位置<br />
GLfloat lightpos[] = { 20.0, 80.0, -50.0, 1.0 };</p>
<p>float Ambient[] = {0.8f, 0.0f, 0.2f, 1.0f};<br />
float Diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};<br />
float specular[]= { 0.4, 0.4, 0.4, 1.0};//鏡面反射<br />
float AmbientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f};<br />
float DiffuseLight[] = { 0.2f, 0.7f, 0.7f, 1.0f};<br />
float SpecularLight[] = {1.0, 1.0, 1.0, 1.0};//鏡面光</p>
<p>void setLight(){<br />
glMaterialfv(GL_FRONT,GL_AMBIENT,Ambient);<br />
glMaterialfv(GL_FRONT,GL_DIFFUSE,Diffuse);<br />
glMaterialfv(GL_FRONT,GL_SPECULAR,specular);<br />
glMaterialf(GL_FRONT,GL_SHININESS,8);<br />
glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientLight);<br />
glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);<br />
glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularLight);<br />
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);<br />
}<br />
void display(void){<br />
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />
glViewport(0, 0, WIDTH, HEIGHT);<br />
glMatrixMode(GL_PROJECTION);<br />
glLoadIdentity();<br />
//視野角,アスペクト比(ウィンドウの幅/高さ),描画する範囲(最も近い距離,最も遠い距離)<br />
gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 1000.0);<br />
glMatrixMode(GL_MODELVIEW);<br />
glLoadIdentity();<br />
//視点の設定<br />
gluLookAt(150.0,100.0,-200.0, //カメラの座標<br />
0.0,0.0,0.0, // 注視点の座標<br />
0.0,1.0,0.0); // 画面の上方向を指すベクトル<br />
//ライトの設定<br />
setLight();<br />
//回転<br />
glRotatef(anglex,1.0f,0.0f,0.0f);//X軸を回転<br />
glsl.ON();//シェーダー描画に切り替え<br />
glutSolidSphere(40.0,16,16);<br />
glsl.OFF();//シェーダー解除<br />
glutSwapBuffers();<br />
}<br />
void idle(void){<br />
anglex+=2.0f;<br />
Sleep(1);<br />
glutPostRedisplay();<br />
}<br />
void Init(){<br />
glsl.InitGLSL("vertex.shader","flagment.shader");<br />
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);<br />
glEnable(GL_DEPTH_TEST);<br />
glEnable(GL_LIGHTING);<br />
glEnable(GL_LIGHT0);<br />
}<br />
void main(int argc, char *argv[]){<br />
glutInitWindowPosition(100, 100);<br />
glutInitWindowSize(WIDTH, HEIGHT);<br />
glutInit(&argc, argv);<br />
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />
glutCreateWindow("スペキュラー");<br />
glutDisplayFunc(display);<br />
glutIdleFunc(idle);<br />
Init();<br />
glutMainLoop();<br />
return;<br />
}</p>
</td>
</tr></tbody></table><p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>