電腦遊戲製作開發設計論壇 首頁 電腦遊戲製作開發設計論壇
任何可以在PC上跑的遊戲都可以討論,主要以遊戲之製作開發為主軸,希望讓台灣的遊戲人有個討論、交流、教學、經驗傳承的園地
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入 

Google
GLSL&GLUT 從環境設定開始的基礎教學(03) - 導入材質

 
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式高級班:DirectX、OpenGL及各種圖型函式庫
上一篇主題 :: 下一篇主題  
發表人 內容
Director
偶而上來逛逛的過客


註冊時間: 2013-11-04
文章: 13

381.66 果凍幣

發表發表於: 2013-11-21, PM 7:43 星期四    文章主題: GLSL&GLUT 從環境設定開始的基礎教學(03) - 導入材質 引言回覆

引言回覆:

 ※2015/7/5補充:
  其實已經過很久了,GLee似乎已經沒再繼續更新,我在寫了這篇教學不久後也改用了GLEW取代Glee,它們的功能及函式名稱其實是幾乎一樣的,安裝方式同其他函式庫
  所以只需要將glee.h及glee.lib改為glew.h及glew.lib就好,這是下載的地方,抓Binaries那個http://glew.sourceforge.net/。
  lib用 lib\Release\Win32 裡面的。



 因為上週在期考,這篇拖了有點久才生出來 Crying or Very sad

 那麼這個章節我們就要開始利用Shader做些有趣的事情。

 這張圖是由兩個材質疊合成的,看起來像是兩張半透明的材質,這是利用Shader的簡單實作。

 這並沒有用到Alpha及GL_BLEND之類的東西,這不過是把兩張圖的顏色加起來除以二得到的結果。

 我想表達的是,學會GLSL可以讓我們真正的控制畫面上每一個像素的顏色。

 以我來說,我當初學習這個的目的就是想做出影子,然而,我最大的問題是在,我不知道怎麼讓該有影子的地方出現影子(顏色變暗),我不懂得如何讓面上的一小塊材質變色,於是乎,這就是GLSL能做到的事情。

 那我們開始來看Code吧!

 簡單來描述一下步驟:
  Step1: 載入材質是務必要有的
  Step2: 告訴Shader我們要用哪張材質來渲染
  Step3: 渲染它!

引言回覆:
Step1


 在這個範例我選擇用人家寫好的函式庫來導入材質,主要是方便,不必自己處理各種檔案的材質。

 我用的是一款叫做Devil的免費函式庫,安裝方式如freeglut,.h放到include、.lib放到lib、dll放到WINDOW資料夾(system32/sysWOW64),最後記得在專案的Linker(連結器)->Additional Dependencies加入你所有額外引入的.lib名稱,那詳細就不再贅述,網址在這http://openil.sourceforge.net/

 這款函式庫的用法有個要注意的地方,在你使用它的功能之前要先預先設定一些東西,不多,四行而已
代碼:
   ilInit();
   iluInit();
   ilutInit();
   ilutRenderer( ILUT_OPENGL );   // 告訴ilut我們要用OpenGL來渲染

 把這四行寫在你做前置設定函式中,或者最少也要放在你開始用它的功能之前。

 設定好之後,我們就可以開始使用他的方便功能了。

 載入材質的部分不像以往我們要設定諸多glTexParameter,只要用ilutGLLoadImage就可以載入可以給OpenGL使用的材質。
 ※當然,如果有需要調整諸如GL_TEXTURE_MIN_FILTER之類的屬性,也還是可以的。

代碼:
   myTex = ilutGLLoadImage( (wchar_t*)"example.jpg" );

 myTex就是材質的ID或是handle。
 ilutGLLoadImage就是這款函式庫要載入檔案給OpenGL的時候用的函式,引數內的const char*要強轉為wchar_t*才能夠給程式使用。
 ※string的話就要用到結構中的c_str()轉成const char*之後再轉為wchar_t*。

 如此,也不必特地去設定多材質,所有的素材都依這種方式引入即可。



 再來的部分會比較複雜,我們要初步介紹Shader使用的資料格式。
 還是一樣附上這篇,和我的解釋可以對照著看,http://nehe.gamedev.net/article/glsl_an_introduction/25007/

 首先每個全域變數都要有以下三個的其中一種性質。
 uniform,當你要從程式傳一些"定量"到Shader中會用到它。
 varying,當你要從vertex shader傳資料到fragment shader的時候會用到。
 attribute,當你要傳一些會隨著渲染不同地方而改變的資料會用到它(我目前只有在vertex buffer object的實作有用到它)。

 他們的用途會在實作中慢慢領略,現在不懂也沒關係,而在這篇我們只會用到uniform還有varying而已。

 介紹完屬性之後,再來要介紹的有一些我們比較會常用到的資料型。
 vec2、vec3、vec4,簡單來說就是二三四維的向量,他們之間可以互相填充,甚麼意思呢?
 例如我可以這樣寫:
代碼:
   vec2 a = vec2( 1.0, 0.5 );
   vec2 b = vec2( 0.3, 1.0 );
   vec4 c = vec4( a, b );      // 這樣c就會是vec4( 1.0, 0.5, 0.3, 1.0)

 我想應該不難懂 Very Happy

 那再來是這一章節要貼材質會用上的sampler2D。
 他是代表一個2D材質的資料,我們之後會利用它來進行貼圖的動作。
 ※其他還有sampler1D、3D、Cube、1DShadow、2DShadow,之後用上了再做介紹。

 那講完這些我們就可以進行第二步驟了。

引言回覆:
Step2-1


 只要第一章程式碼還在,裡面的loadFile、loadShader、initShader沒有更動,我們應該只要修改vertex.vs以及fragment.frag的內容就可以了!
代碼:
// vertex.vs

varying vec2 texcoord;      // 用來存放材質的索引(glTexCoord那類的東西)

void main()
{
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

   texcoord = gl_MultiTexCoord0.st;   // 取得該vertex的texCoord
}


代碼:
// fragment.frag

uniform sampler2D tex;   // 材質1
uniform sampler2D tex2;   // 材質2

varying vec2 texcoord;   // 從vertex shader傳來的vec2

void main()
{
   vec4 texcolor = texture2D(tex, texcoord);   // 依照texcoord傳回材質在該索引的顏色
   vec4 texcolor2 = texture2D(tex2, texcoord);

   gl_FragColor = texcolor;   // 貼上材質tex
   //gl_FragColor = texcolor*0.5 + texcolor2*0.5;   // tex和tex2各混一半
}


 texcoord的格式就是我們要傳資料到fragment shader要用的varying,意義上就是說在vertex shader先把它算一算再送交給fragment shader。
 texture2D詳細的可以看這篇,http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/texturing.php
 gl_MultiTexCoord0.st我們在2-2講。

 那麼Shader就在這邊寫完了,再來就剩下如何告訴他我們要用哪張材質。



Step2-2


 回到我們的C++程式,
代碼:
GLuint myTex, myTex2;

void Initialize()
{
   glMatrixMode( GL_PROJECTION );
   glLoadIdentity();
   gluPerspective( WINDOW_VISION_ANGLE, (float)WINDOW_SIZE_W/(float)WINDOW_SIZE_H, WINDOW_VISION_NEAR, WINDOW_VISION_FAR );

   glEnable( GL_DEPTH_TEST );

   // ilut初始化
   ilInit();
   iluInit();
   ilutInit();
   ilutRenderer(ILUT_OPENGL);

   myTex = ilutGLLoadImage( (wchar_t*)"example.jpg" );   // 匯入example.jpg
   myTex2 = ilutGLLoadImage( (wchar_t*)"example.bmp" );   // 匯入example.bmp

   initShader( "vertex.vs", "fragment.frag" );      // 建立Shader

   glEnable( GL_TEXTURE_2D );
}

 這是我用來做初始設定的函式,基本上跟第一篇的都一樣,只差在ilut的初始化以及引入了兩個圖檔。

 那下一步是關鍵,也是開始運用Shader的基礎,我們要把資料傳進去Shader中,如何做? 利用glUniform以及program_id。
代碼:
void Display()
{
   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
   glClearColor( 0.0, 0.0, 0.0, 1.0 );

   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();

   // 這是我自己定義的camera class, 我用glTranslate和glRotate來代替gluLookAt
   // 當然也可以自己寫gluLookAt, 這個的程式碼我會在文尾貼上
   MainCamera.Control( stateKeyboard, CAM_NO_MOUSE_INPUT );   
   MainCamera.UpdateCamera();

   // 這部分是要點
   // Shader中用的不是我們讀取材質後的那個id
   // 而是這些被定義好的GL_TEXTURE加上一個數字
   // 這代表能夠"同時"被使用的材質數量, 共有0~31, 32張(能夠同時用32張材質渲染一個面)
   // 當然如果一個面只要貼一張圖就用一個就好
   glActiveTexture( GL_TEXTURE0 );   // 選擇一個材質unit
   glBindTexture( GL_TEXTURE_2D, myTex );      // 把你要用的材質綁上去
   glActiveTexture( GL_TEXTURE1 );   // 換下一個
   glBindTexture( GL_TEXTURE_2D, myTex2 );      //綁材質

   // 再來則是傳遞資料到Shader之中
   // glUniform就如同我們使用的諸多gl函式一樣會有1f, 2i, 3d之類的字尾
   // 1i指的就是傳一個整數進去
   // 參數裡面放的第一個, 就是在Shader中對應的那個uniform格式的變數
   // 回憶一下這個-> uniform sampler2D tex;
   // 第二個之後就是我們要傳入的值, 因為是1i所以只有1個整數
   // 傳的東西就是GL_TEXTURE0 <-這個0
   glUniform1i( glGetUniformLocation( program, "tex" ), 0 );   // 剛剛glActiveTexture綁的是myTex
   glUniform1i( glGetUniformLocation( program, "tex2" ), 1 );   // 這個綁的是myTex2

   glBegin(GL_QUADS);
   glTexCoord2f( 1, 1 );      //這個就是剛剛在vertex.vs中看到的gl_MultiTexCoord
   glVertex3f(1, 1, -5);
   glTexCoord2f( 0, 1 );
   glVertex3f(-1, 1, -5);
   glTexCoord2f( 0, 0 );
   glVertex3f(-1, -1, -5);
   glTexCoord2f( 1, 0 );
   glVertex3f(1, -1, -5);
   glEnd();

   glutSwapBuffers();
}

 OK! 大多的東西已經在註解中介紹完了。

 剩下要提的有兩個。
 第一個是介紹vertex.vs中的gl_MultiTexCoord.st的那個.st是什麼東西。
 事實上它就是大家很熟悉的材質的ST座標,至於為什麼會這樣寫是因為gl_MultiTexCoord是一個vec4,而我們要把他轉成跟texcoord一樣的vec2才有的動作。

 這個vec4很有意思,你可以用xyzw、rgba或是stpq來自由取得其中特定幾項。
 例如說:
代碼:
   vec4 a = vec4( 1.0, 0.5, 0.3, 1.0 );
   vec2 b = a.yz;      // 這樣b就會是vec2( 0.5, 0.3 )
   vec3 c = a.xzw;      // 這樣c就會是vec3( 1.0, 0.3, 1.0 )
   vec3 d = a.rba;      // 這個結果會跟c一樣

 當然,要只取其中一項也是可以的。

 再來要提的是,可能有些眼尖的朋友會發現,這樣寫不就跟平常渲染材質沒什麼兩樣嗎?
 同樣都是先glBindTexture之後設定glTexCoord2f,差別在哪裡呢?

 差別就在,我們現在可以操作fragment.frag的內容來改變我們貼上的圖。
 我們可以指定gl_FragColor為tex或是tex2,甚至加起來除以二或多少,都可以透過修改fragment.frag就能夠改變程式而不必修改程式碼。

 我想表達的是,我們終於開始利用Shader來控制渲染的功能了! (灑花



 那麼,大家可以開始嘗試用兩張三張或是更多的圖來混和,下一章節沒意外的話會介紹光線的計算,最後附上程式碼。

Example in VC++2012

代碼:
// allheader.h
#ifndef ALLHEADER_H
#define ALLHEADER_H

#include <GL\GLee.h>
#include <GL\freeglut.h>
#include <iostream>
#include <fstream>
#include <string>
#include <math.h>

#define ILUT_USE_OPENGL
#include <IL/il.h>
#include <IL/ilu.h>
#include <IL/ilut.h>

#define PI 3.14159265         // 圓周率

struct vector3
{
   float x, y, z;
};

#endif

代碼:
// camera.h
#ifndef CAMERA_H
#define CAMERA_H

#include "allheader.h"

enum inputType{
   CAM_NO_MOUSE_INPUT = 0,
   CAM_MOUSE_LEFT,
   CAM_MOUSE_RIGHT,
   CAM_WHEELMOUSE_UP,
   CAM_WHEELMOUSE_DOWN,
   CAM_MOUSE_MOTION_LEFT,
   CAM_MOUSE_MOTION_RIGHT
};

class camera{
   vector3 loc;
   float camPitch, camYaw;
   float moveRate;
   float mouseRate;

   void lockCamera();
   void moveCameraHori( float dir );
   void moveCameraVert( float dir );

   public:
      camera();
      camera( vector3 loc);
      camera( vector3 loc, float yaw, float pitch );
      camera( vector3 loc, float yaw, float pitch, float moveR, float mouseR  );

      void Control( bool* stateKeyboard, int stateMouse, int windowSizeW = NULL, int windowSizeH = NULL, int bufferX = NULL, int bufferY = NULL );
      void UpdateCamera( );

      vector3 getVector();
      vector3 getLocation();
      float getPitch();
      float getYaw();
      float getMoveRate();
      float getMouseRate();
      
      void setLocation(vector3 vec);
      void lookAt(float pitch,float yaw);
      void setSpeed( float moveR, float mouseR );
      void showLocation();
};

#endif

代碼:
// camera.cpp
#include "camera.h"

camera::camera()
{
   loc.x = 0.0;
   loc.y = 0.0;
   loc.z = 0.0;
   camPitch = 0;
   camYaw = 0;
   moveRate = 0.2;
   mouseRate = 0.2;
}
camera::camera( vector3 l )
{
   loc.x = l.x;
   loc.y = l.y;
   loc.z = l.z;

   camPitch = 0;
   camYaw = 0;
   moveRate = 0.2;
   mouseRate = 0.2;
}

camera::camera( vector3 l, float yaw, float pitch )
{
   loc.x = l.x;
   loc.y = l.y;
   loc.z = l.z;

   camPitch = pitch;
   camYaw = yaw;
   moveRate = 0.2;
   mouseRate = 0.2;
}

camera::camera( vector3 l, float yaw, float pitch, float moveR, float mouseR )
{
   loc.x = l.x;
   loc.y = l.y;
   loc.z = l.z;

   camPitch = pitch;
   camYaw = yaw;
   moveRate = moveR;
   mouseRate = mouseR;
}

void camera::lockCamera()
{
   if(camPitch > 90)
      camPitch = 90;
   if(camPitch < -90)
      camPitch = -90;
   if(camYaw < 0.0)
      camYaw += 360.0;
   if(camYaw > 360.0)
      camYaw -= 360;
}

void camera::moveCameraHori( float dir )
{
   float rad = (camYaw+dir)*PI/180.0;
   loc.x += sin(rad)*moveRate;
   loc.z += cos(rad)*moveRate;
}

void camera::moveCameraVert( float dir )
{
   float rad = (camPitch+dir)*PI/180.0;
   loc.y -= sin(rad)*moveRate;   
}

void camera::Control( bool* stateKeyboard, int stateMouse, int windowSizeW, int windowSizeH, int bufferX, int bufferY )
{
   // mouse
   if( stateMouse != CAM_NO_MOUSE_INPUT )
   {
      if( stateMouse == CAM_MOUSE_MOTION_LEFT ){
         camYaw += mouseRate*(bufferX/2.0);
         camPitch += mouseRate*(bufferY/2.0);
      }
      if( stateMouse == CAM_WHEELMOUSE_UP ){      
         if( camPitch != 90 && camPitch != -90 )
            moveCameraHori(0.0);
         moveCameraVert(0.0);
      }
      if( stateMouse == CAM_WHEELMOUSE_DOWN ){   
         if( camPitch != 90 && camPitch != -90 )
            moveCameraHori(180.0);
         moveCameraVert(180.0);
      }
      if( stateMouse == CAM_MOUSE_MOTION_RIGHT ){
         if( bufferX > 0 )
            moveCameraHori(90.0);
         else
            moveCameraHori(270.0);
      }
      lockCamera();
   }

   // keyboard
   if( stateKeyboard[(unsigned int)'w'] )
   {
      if( camPitch != 90 && camPitch != -90 )
         moveCameraHori(0.0);
      moveCameraVert(0.0);
   }
   if( stateKeyboard[(unsigned int)'s'] )
   {
      if( camPitch != 90 && camPitch != -90 )
         moveCameraHori(180.0);
      moveCameraVert(180.0);
   }
   if( stateKeyboard[(unsigned int)'a'] )
   {
      moveCameraHori(90.0);
   }
   if( stateKeyboard[(unsigned int)'d'] )
   {
      moveCameraHori(270.0);   
   }
   if( stateKeyboard[(unsigned int)'h'] )
   {
      showLocation();   
   }

   // result
   glRotatef( -camPitch, 1.0, 0.0, 0.0 );
   glRotatef( -camYaw, 0.0, 1.0, 0.0 );
}

void camera::UpdateCamera()
{   
   glTranslatef( loc.x, loc.y, loc.z );
}

vector3 camera::getVector()
{
   vector3 tmp;
   tmp.x = -cos(camPitch*PI/180.0)*sin(camYaw*PI/180.0);
   tmp.y = sin(camPitch*PI/180.0);
   tmp.z = -cos(camPitch*PI/180.0)*cos(camYaw*PI/180.0);

   return tmp;
}
vector3 camera::getLocation()
{
   return loc;
}

float camera::getPitch()
{
   return camPitch;
}

float camera::getYaw()
{
   return camYaw;
}

float camera::getMoveRate()
{
   return moveRate;
}

float camera::getMouseRate()
{
   return mouseRate;
}

void camera::setLocation( vector3 vec )
{
   loc.x = vec.x;
   loc.y = vec.y;
   loc.z = vec.z;
}

void camera::lookAt( float pitch, float yaw )
{
   camPitch = pitch;
   camYaw = yaw;
}

void camera::setSpeed( float moveR, float mouseR )
{
   moveRate = moveR;
   mouseRate = mouseR;
}

void camera::showLocation()
{
   std::cout << "Location: " << loc.x << ", " << loc.y << ", " << loc.z << std::endl
      << "Direction: " << camPitch << ", " << camYaw << std::endl;
}

代碼:
// main.cpp
//---------------------------------------------------------
// 作者: DR
// 2013/11/21
//
// GLSL&GLUT 從環境設定開始的基礎教學(03) - 導入材質
//---------------------------------------------------------
//
#include "allheader.h"
#include "camera.h"

#define WINDOW_SIZE_W 500      // 起始視窗寬度
#define WINDOW_SIZE_H 500      // 起始視窗高度
#define WINDOW_VISION_ANGLE 45   // 視角
#define WINDOW_VISION_NEAR 1   // 最近視野
#define WINDOW_VISION_FAR 10001   // 最遠視野

bool stateKeyboard[256] = { false };

GLuint windowHandle;
int win_size_w = WINDOW_SIZE_W,
   win_size_h = WINDOW_SIZE_H;

camera MainCamera;

GLuint myTex, myTex2;

void loadFile( const char* filename, std::string &string )
{
   std::ifstream fp(filename);
   if( !fp.is_open() ){
      std::cout << "Open <" << filename << "> error." << std::endl;
      return;
   }

   char temp[300];
   while( !fp.eof() ){
      fp.getline( temp, 300 );
      string += temp;
      string += '\n';
   }

   fp.close();
}

GLuint loadShader(std::string &source, GLenum type)
{
   GLuint ShaderID;
   ShaderID = glCreateShader( type );      // 告訴OpenGL我們要創的是哪種shader

   const char* csource = source.c_str();   // 把std::string結構轉換成const char*

   glShaderSource( ShaderID, 1, &csource, NULL );      // 把程式碼放進去剛剛創建的shader object中
   glCompileShader( ShaderID );                  // 編譯shader
   char error[1000] = "";
   glGetShaderInfoLog( ShaderID, 1000, NULL, error );   // 這是編譯過程的訊息, 錯誤什麼的把他丟到error裡面
   std::cout << "Complie status: \n" << error << std::endl;   // 然後輸出出來

   return ShaderID;
}

GLuint vs, fs, program;      // 用來儲存shader還有program的id

void initShader(const char* vname, const char* fname)
{
   std::string source;

   loadFile( vname, source );      // 把程式碼讀進source
   vs = loadShader( source, GL_VERTEX_SHADER );   // 編譯shader並且把id傳回vs
   source = "";
   loadFile( fname, source );
   fs = loadShader( source, GL_FRAGMENT_SHADER );

   program = glCreateProgram();   // 創建一個program
   glAttachShader( program, vs );   // 把vertex shader跟program連結上
   glAttachShader( program, fs );   // 把fragment shader跟program連結上

   glLinkProgram( program );      // 根據被連結上的shader, link出各種processor
   glUseProgram( program );      // 然後使用它
}

void clean()
{
   glDetachShader( program, vs );
   glDetachShader( program, fs );
   glDeleteShader( vs );
   glDeleteShader( fs );
   glDeleteProgram( program );
}

void Initialize()
{
   glMatrixMode( GL_PROJECTION );
   glLoadIdentity();
   gluPerspective( WINDOW_VISION_ANGLE, (float)WINDOW_SIZE_W/(float)WINDOW_SIZE_H, WINDOW_VISION_NEAR, WINDOW_VISION_FAR );

   glEnable( GL_DEPTH_TEST );

   ilInit();
   iluInit();
   ilutInit();
   ilutRenderer(ILUT_OPENGL);

   myTex = ilutGLLoadImage( (wchar_t*)"example.jpg" );   
   myTex2 = ilutGLLoadImage( (wchar_t*)"example.bmp" );

   initShader( "vertex.vs", "fragment.frag" );

   glEnable( GL_TEXTURE_2D );
}

void Display()
{
   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
   glClearColor( 0.0, 0.0, 0.0, 1.0 );

   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();

   MainCamera.Control( stateKeyboard, CAM_NO_MOUSE_INPUT );
   MainCamera.UpdateCamera();

   glActiveTexture( GL_TEXTURE0 );
   glBindTexture( GL_TEXTURE_2D, myTex );
   glActiveTexture( GL_TEXTURE1 );
   glBindTexture( GL_TEXTURE_2D, myTex2 );
   
   glUniform1i( glGetUniformLocation( program, "tex" ), 0 );
   glUniform1i( glGetUniformLocation( program, "tex2" ), 1 );

   glBegin(GL_QUADS);
   glTexCoord2f( 1, 1 );
   glVertex3f(1, 1, -5);
   glTexCoord2f( 0, 1 );
   glVertex3f(-1, 1, -5);
   glTexCoord2f( 0, 0 );
   glVertex3f(-1, -1, -5);
   glTexCoord2f( 1, 0 );
   glVertex3f(1, -1, -5);
   glEnd();

   glutSwapBuffers();
}

void Reshape( int w, int h )
{
   glViewport( 0, 0, w, h );

   if( h == 0 ) h = 1;

   win_size_w = w;
   win_size_h = h;

   glMatrixMode( GL_PROJECTION );
   glLoadIdentity();
   gluPerspective( WINDOW_VISION_ANGLE, (float)w/(float)h, WINDOW_VISION_NEAR, WINDOW_VISION_FAR );

   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();   
}

bool MOUSE_LEFT = false, MOUSE_RIGHT = false;
int mouse_x = 0, mouse_y = 0, old_mouse_x = 0, old_mouse_y = 0;

void Mouse( int button, int state, int x, int y )
{
   switch( button ){
   case GLUT_LEFT_BUTTON:
      if( state ){
         MOUSE_LEFT = false;

         mouse_x = 0;
         mouse_y = 0;
      }
      else{
         MainCamera.Control( stateKeyboard, CAM_MOUSE_LEFT, win_size_w, win_size_h, x, y );

         MOUSE_LEFT = true;
         old_mouse_x = x;
         old_mouse_y = y;
      }
      break;
   case GLUT_RIGHT_BUTTON:
      if( state ){
         MOUSE_RIGHT = false;

         mouse_x = 0;
         mouse_y = 0;
      }
      else{
         MainCamera.Control( stateKeyboard, CAM_MOUSE_RIGHT, win_size_w, win_size_h, x, y );

         MOUSE_RIGHT = true;
         old_mouse_x = x;
         old_mouse_y = y;
      }
      break;
   }
}

void MouseWheel( int wheel, int direction, int x, int y )
{
   switch( direction ){
   case 1:
      MainCamera.Control( stateKeyboard, CAM_WHEELMOUSE_UP );
      break;
   case -1:
      MainCamera.Control( stateKeyboard, CAM_WHEELMOUSE_DOWN );
      break;
   }
}

void MotionMouse( int x, int y )
{
   if( MOUSE_LEFT ){
      mouse_x = x - old_mouse_x;
      mouse_y = y - old_mouse_y;

      MainCamera.Control( stateKeyboard, CAM_MOUSE_MOTION_LEFT, win_size_w, win_size_h, mouse_x, mouse_y );   

      old_mouse_x = x;
      old_mouse_y = y;
   }

   if( MOUSE_RIGHT ){
      mouse_x = x - old_mouse_x;
      mouse_y = y - old_mouse_y;

      MainCamera.Control( stateKeyboard, CAM_MOUSE_MOTION_RIGHT, win_size_w, win_size_h, mouse_x, mouse_y );   

      old_mouse_x = x;
      old_mouse_y = y;
   }
}

void Keyboard( unsigned char key, int x, int y )
{
   stateKeyboard[key] = true;
}

void KeyboardUp( unsigned char key, int x, int y )
{
   stateKeyboard[key] = false;
}

void Timer( int t )
{
   glutPostRedisplay();
   glutTimerFunc( 1000/60, Timer, 1 );
}

int main( int argc, char** argv )
{
   glutInit( &argc, argv );

   glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
   glutInitWindowPosition( 0, 0 );
   glutInitWindowSize( WINDOW_SIZE_W, WINDOW_SIZE_H );

   windowHandle = glutCreateWindow( "GLUT&GLSL example" );
   Initialize();

   glutDisplayFunc( Display );
   glutReshapeFunc( Reshape );
   glutMouseFunc( Mouse );
   glutMouseWheelFunc( MouseWheel );
   glutMotionFunc( MotionMouse );
   glutKeyboardFunc( Keyboard );
   glutKeyboardUpFunc( KeyboardUp );
   glutTimerFunc( 1000/60, Timer, 0 );

   glutMainLoop();

   return 0;
}


 Happy coding! Very Happy
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件 參觀發表人的個人網站
從之前的文章開始顯示:   
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式高級班:DirectX、OpenGL及各種圖型函式庫 所有的時間均為 台灣時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
可以 在這個版面附加檔案
可以 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作