環境光

現実世界では、太陽や照明からの光が様々な物体に反射して光が直接当たらない場所でも
間接的に反射してきた光によってある一定の明るさになっています。
この空間に溢れる光を環境光といいます。
CGでこれを再現するにはラジオシティやグローバルイルミネーションなどがありますが、
計算コストが非常に高く、ゲームなどのリアルタイムな画面更新が求められるプログラムでは
とても使う事はできません。
そこで、一般的には割とそれらしく見せるためにシーン全体に影響する一定の色を環境光として
使います。
vec4 ambient = gl_FrontLightProduct[0].ambient; で、OpenGLからアンビエント情報を受け取ります。
これを紐解いていくと、
glLightfv(GL_LIGHT0, GL_AMBIENT, Light); で設定したライトの光の範囲内で
glMaterialfv(GL_FRONT,GL_AMBIENT,Ambient); の反射をします。
一般的に使用される環境光の正体がわかりましたね? その実体は、ただの色です。
これに拡散反射光や鏡面反射光などを掛け合わせて、より、それらしく見えるようにするのが
一般的な方法です。

 

vertex.shader

void main(void)
{
 vec4 ambient = gl_FrontLightProduct[0].ambient;
 gl_FrontColor = ambient;
 gl_Position = ftransform();//クリップ空間へ
}

GLSL.h

#pragma once
 #include <stdio.h>
 
//GLSLクラス
 class GLSL{
 public:
  GLuint ShaderProg;
  GLuint VertexShader, FragmentShader;
  void ReadShaderCompile(GLuint Shader, const char *File);//shader fileを読み込みコンパイルする
  void Link( GLuint Prog );//リンクする
  void InitGLSL(const char *VertexFile);//GLSLの初期化
  void InitGLSL(const char *VertexFile, const char *FragmentFile);//GLSLの初期化
  void ON();//シェーダー描画に切り替え
  void OFF();//シェーダー解除
  ~GLSL();
 };
 
 void GLSL::ReadShaderCompile(GLuint Shader, const char *File){
    FILE *fp;
    char *buf;
    GLsizei size, len;
    GLint compiled;
 
    fopen_s(&fp,File, "rb");
    if(!fp) printf("ファイルを開くことができません %s\n", File);
 
    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
 
   buf = (GLchar *)malloc(size);
    if (buf == NULL) {
      printf("メモリが確保できませんでした \n");
    }
 
    fseek(fp, 0, SEEK_SET);
    fread(buf, 1, size, fp);
    glShaderSource(Shader, 1, (const GLchar **)&buf, &size);
    free(buf);
    fclose(fp);
 
    glCompileShader(Shader);
    glGetShaderiv( Shader, GL_COMPILE_STATUS, &compiled );
 
   if ( compiled == GL_FALSE )
    {
     printf( "コンパイルできませんでした!!: %s \n ", File);
     glGetProgramiv( Shader, GL_INFO_LOG_LENGTH, &size );
     if ( size > 0 )
     {
      buf = (char *)malloc(size);
      glGetShaderInfoLog( Shader, size, &len, buf);
      printf(buf);
      free(buf);
     }
    }
  }
 
 void GLSL::Link( GLuint Prog ){
    GLsizei size, len;
    GLint linked;
    char *infoLog ;
 
   glLinkProgram( Prog );
 
   glGetProgramiv( Prog, GL_LINK_STATUS, &linked );
 
   if ( linked == GL_FALSE ){
    printf("リンクできませんでした!! \n");
    
    glGetProgramiv( Prog, GL_INFO_LOG_LENGTH, &size );
    if ( size > 0 ){
     infoLog = (char *)malloc(size);
     glGetProgramInfoLog( Prog, size, &len, infoLog );
     printf(infoLog);
     free(infoLog);
    }
   }
 }
 
void GLSL::InitGLSL(const char *VertexFile){
    GLenum err = glewInit();
    if (err != GLEW_OK)
    {
     printf("Error: %s\n", glewGetErrorString(err));
    }
    printf("VENDOR= %s \n", glGetString(GL_VENDOR));
    printf("GPU= %s \n", glGetString(GL_RENDERER));
    printf("OpenGL= %s \n", glGetString(GL_VERSION));
    printf("GLSL= %s \n", glGetString(GL_SHADING_LANGUAGE_VERSION));
    VertexShader = glCreateShader(GL_VERTEX_SHADER);
    ReadShaderCompile(VertexShader, VertexFile);
    ShaderProg = glCreateProgram();
    glAttachShader(ShaderProg, VertexShader);
    glDeleteShader(VertexShader);
    Link(ShaderProg);
  }
 
 
void GLSL::InitGLSL(const char *VertexFile, const char *FragmentFile){
    GLenum err = glewInit();
    if (err != GLEW_OK)
    {
     printf("Error: %s\n", glewGetErrorString(err));
    }
    printf("VENDOR= %s \n", glGetString(GL_VENDOR));
    printf("GPU= %s \n", glGetString(GL_RENDERER));
    printf("OpenGL= %s \n", glGetString(GL_VERSION));
    printf("GLSL= %s \n", glGetString(GL_SHADING_LANGUAGE_VERSION));
 
   VertexShader = glCreateShader(GL_VERTEX_SHADER);
    FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 
   ReadShaderCompile(VertexShader, VertexFile);
    ReadShaderCompile(FragmentShader, FragmentFile);
 
   ShaderProg = glCreateProgram();
 
    glAttachShader(ShaderProg, VertexShader);
    glAttachShader(ShaderProg, FragmentShader);
 
    glDeleteShader(VertexShader);
    glDeleteShader(FragmentShader);
    Link(ShaderProg);
  }
 
void GLSL::ON(){
  glUseProgram(ShaderProg);
 }
 
void GLSL::OFF(){
  glUseProgram(0);
 }
 
GLSL::~GLSL(){
  glDeleteProgram(ShaderProg);
 }
 

 

main.cpp

#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib, "glew32.lib")

#include <stdio.h>
#include <GL/glew.h>
#include <GL/freeglut/freeglut.h>
#include "GLSL.h"

#define WIDTH 320
#define HEIGHT 240

GLSL glsl;
//ライトの位置
GLfloat lightpos[] = { 20.0, 80.0, 50.0, 1.0 };
//環境光
float Ambient[] = {0.0f, 0.0f, 0.8f, 1.0f};
float Light[] = { 1.0f, 1.0f, 1.0f, 1.0f};

void setLight(){
 glMaterialfv(GL_FRONT,GL_AMBIENT,Ambient);
 glLightfv(GL_LIGHT0, GL_AMBIENT, Light);
 glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
}
void display(void){

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glViewport(0, 0, WIDTH, HEIGHT);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 //視野角,アスペクト比(ウィンドウの幅/高さ),描画する範囲(最も近い距離,最も遠い距離)
 gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 100.0);
 glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
 //視点の設定
 gluLookAt(15.0,20.0,-5.0, //カメラの座標
      0.0,0.0,0.0, // 注視点の座標
     0.0,1.0,0.0); // 画面の上方向を指すベクトル
 //ライトの設定
 setLight();

 //回転
 glRotatef(280,1.0f,0.0f,0.0f);//X軸を回転
 glsl.ON();//シェーダー描画に切り替え
 glutSolidCone(2.0, 5.0, 8, 8);
 glsl.OFF();//シェーダー解除

 glutSwapBuffers();
}
void idle(void){
 glutPostRedisplay();
}
void Init(){
 glsl.InitGLSL("vertex.shader");
 glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
 glEnable(GL_DEPTH_TEST);
 glEnable(GL_LIGHTING);
 glEnable(GL_LIGHT0);

}
void main(int argc, char *argv[]){
 glutInitWindowPosition(100, 100);
 glutInitWindowSize(WIDTH, HEIGHT);
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
 glutCreateWindow("アンビエント");
 glutDisplayFunc(display);
 glutIdleFunc(idle);
 Init();
 glutMainLoop();
 return;
}

 

 

 

 

 

 

 

最終更新:2014年05月01日 17:44
添付ファイル