- 追加された行はこの色です。
- 削除された行はこの色です。
*OpenGLで描画までのシンプルなプロジェクト [#s05334bc]
Windows / Androidで動作確認
***注意点 [#qcde754e]
シェーダーはmidiump / lowpを使って型を固定しておかないとAndroidでシェーダのコンパイルで失敗する
Windows / Androidで動作確認。Windowを作って描画するまでの最小セット。
シェーダーはmidiump / lowpを使って型を固定しておかないとAndroidでシェーダのコンパイルで失敗するので注意!
[[SimpleGLTestのダウンロード>http://garuru.co.jp/files/forWiki/SimpleGLTest.zip]]
**レンダーテクスチャを使って描画する [#g5c538ab]
//----------------------------------------------------
//
// シェーダーテスト用の最小プログラム
//
//----------------------------------------------------
#include <windows.h>
#include <windowsx.h>
#include <lib/glew-2.1.0/include/GL/glew.h>
//#include <GLES2/gl2.h>
//#include <GLES2/gl2ext.h>
#define WINDOW_WIDTH 512
#define WINDOW_HEIGHT 512
#define FPS (60)
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "lib/glew-2.1.0/lib/Release/x64/glew32.lib")
//buffer for texture
int TextureWidth=256,TextureHeight=256;
unsigned int texImage1[256 * 256 * 4]; //image buffer for ue4 texture
unsigned int texImage2[256 * 256 * 4]; //image buffer for render texture
unsigned int texImage3[256 * 256 * 4]; //image buffer for capture texture
//shader programs
const GLchar *vtxShader1[] = {
"#version 330\n",
"in vec3 a_position;\n",
"in vec2 a_texCoord;\n",
"in vec4 a_color;\n",
"out vec4 v_vtxColor;\n",
"out vec2 v_texCoord;\n",
"void main(void)\n",
"{\n",
"gl_Position = vec4( a_position , 1 );\n",
"v_vtxColor = a_color;\n",
"v_texCoord = a_texCoord;\n",
"}\n",
};
const GLchar *pxlShader1[] = {
"#version 330\n",
"in vec4 v_vtxColor;\n",
"in int v_palColor;\n",
"in vec2 v_texCoord;\n",
"uniform sampler2D u_textureID1;\n",
"void main(void)\n",
"{\n",
" vec4 color1 = texture2D( u_textureID1 , v_texCoord.xy );\n",
" gl_FragColor = color1;\n",
"}\n",
};
struct StWindow
{
HINSTANCE m_hInstance;
HWND m_hWindow;
WPARAM m_wParam;
HACCEL m_hAccel;
HDC m_WinDC;
bool g_bExit = false;
} Window;
struct StOpenGL
{
HGLRC m_hRC;
GLuint m_sTexIndex[8];
GLuint shaderProgram;
int Sequence;
GLuint s_offscreen_fbo;
} OpenGL;
typedef struct StCustomVertex2
{
float x, y, z, rhw;
unsigned int argb;
float u, v;
} StCustomVertex2;
//Windows
void makeWindow( );
void action();
void render();
void vSync();
LRESULT CALLBACK WindowProc(HWND hw, UINT iMsg, WPARAM wParam, LPARAM lParam);
//openGL
void initGL();
void initTexture();
void initShader();
void drawGL();
void drawPrim( StCustomVertex2 *pVertex , int width , int height );
//extern unsigned char ue4[];
#if 1
int APIENTRY wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
//Windows Main
OpenGL.Sequence = 0;
OpenGL.s_offscreen_fbo = -1;
Window.m_hInstance = hInstance;
//make Window
makeWindow();
//show Windows
ShowWindow( Window.m_hWindow, nCmdShow );
//main loop
while(!Window.g_bExit)
{
action();
vSync();
SwapBuffers( Window.m_WinDC );
}
}
void makeWindow( )
{
//make window
WNDCLASSEX wndClass;
wndClass.cbSize = sizeof(wndClass);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = Window.m_hInstance;
wndClass.hIcon = NULL;
wndClass.hCursor = NULL;
wndClass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = TEXT("glTest");
wndClass.hIconSm = NULL;
ATOM hr = RegisterClassEx(&wndClass);
RECT desktop;
GetWindowRect(GetDesktopWindow(), (LPRECT)&desktop);
int x, y, w, h;
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, WS_OVERLAPPEDWINDOW|WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, FALSE );
w = rect.right - rect.left;
h = rect.bottom - rect.top;
x = (desktop.right - desktop.left)/2 - w/2;
y = (desktop.bottom - desktop.top )/2 - h/2;
if( x < 0) x = 0;
if( y < 0) y = 0;
Window.m_hWindow = CreateWindow(
TEXT("glTest"),
TEXT("ShaderTest"),
WS_OVERLAPPEDWINDOW|WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE,
x,
y,
w,
h,
NULL,
NULL,
Window.m_hInstance,
NULL);
Window.m_WinDC = GetDC( Window.m_hWindow );
}
void vSync()
{
//------------------------------------------
//wait vsync
//------------------------------------------
MSG msg;
static LONGLONG before = 0;
static LONGLONG vsyncratio = 0;
LONGLONG time;
QueryPerformanceCounter( (LARGE_INTEGER*)&time );
if( vsyncratio == 0 )
{
// init vsync ratio
QueryPerformanceCounter ( (LARGE_INTEGER*)&before);
QueryPerformanceFrequency((LARGE_INTEGER*)&vsyncratio);
vsyncratio = vsyncratio / FPS;
before = time;
}
do
{
// wait vsync
QueryPerformanceCounter( (LARGE_INTEGER*)&time );
while(PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if( !GetMessage( &msg, NULL, 0, 0 ) )
{
return;
}
if ( !TranslateAccelerator( Window.m_hWindow , Window.m_hAccel , &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
}
while( time < ( before + vsyncratio ) );
before = time;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
//------------------------------------------
//windows procedure
//------------------------------------------
switch (iMsg) {
case WM_CREATE:
break;
case WM_CLOSE:
DestroyWindow( hWnd );
break;
case WM_DESTROY:
Window.g_bExit = true;
PostQuitMessage(0);
return 0;
case WM_SYSCOMMAND:
case WM_COMMAND:
default:
break;
}
return DefWindowProc( hWnd, iMsg, wParam, lParam );
}
#endif
//-------------------------------------------------------------
// OpenGL code
//-------------------------------------------------------------
void action()
{
if ( OpenGL.Sequence == 0 )
{
//init
initGL();
initTexture();
initShader();
glEnable ( GL_TEXTURE_2D );
/*毒*/// glEnable ( GL_NORMALIZE );
/*毒*/// glEnable ( GL_ALPHA_TEST );
glEnable ( GL_BLEND );
glDisable( GL_DEPTH_TEST );
OpenGL.Sequence ++;
}
drawGL();
}
void initGL()
{
//----------------------------------------------------------------------
// OpenGL initialize
//----------------------------------------------------------------------
#if 1
int pixelFormat;
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
1, // no stencil buffer
1, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
pixelFormat = ChoosePixelFormat(Window.m_WinDC, &pfd);
SetPixelFormat(Window.m_WinDC, pixelFormat, &pfd);
OpenGL.m_hRC = wglCreateContext(Window.m_WinDC);
wglMakeCurrent(Window.m_WinDC, OpenGL.m_hRC);
GLenum err = glewInit();
//matrix
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
//Reset
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
BOOL(WINAPI *wglSwapIntervalEXT)(int) = NULL;
wglSwapIntervalEXT = (BOOL(WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT)
{
wglSwapIntervalEXT(0);
}
#endif
}
void initShader()
{
//----------------------------------------------------------------------
// init shader
//----------------------------------------------------------------------
GLint status;
GLsizei bufSize;
GLsizei length;
GLchar *infoLog;
//make program
OpenGL.shaderProgram = glCreateProgram();
//compile vtxShader
GLuint vshader;
vshader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vshader, sizeof(vtxShader1) / sizeof(vtxShader1[0]), (GLchar const* const*)vtxShader1, NULL);
glCompileShader(vshader);
glGetShaderiv(vshader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
glGetShaderiv(vshader, GL_INFO_LOG_LENGTH, &bufSize);
infoLog = (GLchar*)malloc(bufSize);
glGetShaderInfoLog(vshader, bufSize, &length, infoLog);
infoLog[512 - 1] = 0x00;
free(infoLog);
}
//compile pxlShader
GLuint pshader;
pshader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(pshader, sizeof(pxlShader1) / sizeof(pxlShader1[0]), (GLchar const* const*)pxlShader1, NULL);
glCompileShader(pshader);
glGetShaderiv(pshader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
glGetShaderiv(pshader, GL_INFO_LOG_LENGTH, &bufSize);
infoLog = (GLchar*)malloc(bufSize);
glGetShaderInfoLog(pshader, bufSize, &length, infoLog);
free(infoLog);
}
//attach prog program
glAttachShader( OpenGL.shaderProgram , vshader );
glAttachShader( OpenGL.shaderProgram , pshader );
//link shader program
glLinkProgram ( OpenGL.shaderProgram );
glGetProgramiv(OpenGL.shaderProgram, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
glGetProgramiv(OpenGL.shaderProgram, GL_INFO_LOG_LENGTH, &bufSize);
infoLog = (GLchar*)malloc(bufSize);
glGetProgramInfoLog(OpenGL.shaderProgram, bufSize, &length, infoLog);
free(infoLog);
}
glDeleteShader( vshader );
glDeleteShader( pshader );
}
void initTexture()
{
//----------------------------------------------------------------------
//init texture x2
//----------------------------------------------------------------------
glGenTextures( 8, OpenGL.m_sTexIndex );
//make src texture 1( ue4 )
unsigned int argb;
for (int ii = 0; ii < 256 * 256 * 1;ii++)
{
argb = *(int*)(&texImage1[ii*4]);
texImage1[ii] = ((argb>>24)&0xff)<<24 | ((argb>>16)&0xff)<<8 | ((argb>>8)&0xff)<<16 | ((argb>>0)&0xff)<<0; //ue4
}
//make dst texture 2( noise )
for (int ii = 0; ii < 512 * 512 * 1;ii++)
{
texImage2[ii] = 0xff000000 | (rand()%255)<<16 | (rand()%255)<<8 | (rand()%255)<<0 ; //noise
}
// bind texture1
glBindTexture( GL_TEXTURE_2D, OpenGL.m_sTexIndex[0] );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage1 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); //<--- important!
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
// bind texture2
glBindTexture( GL_TEXTURE_2D, OpenGL.m_sTexIndex[1] );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage2 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
// bind texture3
glBindTexture( GL_TEXTURE_2D, OpenGL.m_sTexIndex[2] );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage3 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
//--------------------------------------------------------------
//create frame buffer object( fbo ) from texture
//--------------------------------------------------------------
if( OpenGL.s_offscreen_fbo != -1 )
{
glDeleteFramebuffers( 1 , &OpenGL.s_offscreen_fbo );
}
glGenFramebuffers( 1, &OpenGL.s_offscreen_fbo );
glBindFramebuffer( GL_FRAMEBUFFER, OpenGL.s_offscreen_fbo );
//attach texture as color buffer of frame buffer
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OpenGL.m_sTexIndex[1], 0 );
//restore frame buffer state
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glBindTexture( GL_TEXTURE_2D, 0 );
}
void drawGL()
{
//----------------------------------------------------------------------
//rendering
//----------------------------------------------------------------------
//clear bg( red )
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glClearColor( 1.0f, 0.0f, 0.0f, 1.f );
glClear( GL_COLOR_BUFFER_BIT );
render();
//restore default
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
// glActiveTexture(GL_TEXTURE0 + 0);
// glActiveTexture(GL_TEXTURE0 + 1);
}
void render()
{
//----------------------------------------------------------------------
//rendering
//----------------------------------------------------------------------
StCustomVertex2 pVertex1[4] = {
//rect1 Z
{ 0.f ,0.f ,0.f ,1.f , 0xffffffff , 0.f ,0.f },
{ 256.f ,0.f ,0.f ,1.f , 0xffffffff , 1.0 ,0.0 },
{ 0.f ,256.f ,0.f ,1.f , 0xffffffff , 0.0 ,1.0 },
{ 256/2.f ,256.f ,0.f ,1.f , 0xffffffff , 1.0 ,1.0 },
};
StCustomVertex2 pVertex2[4] = {
//rect2
{ 256 ,256 ,0 ,1 , 0xffffffff , 0 ,0 },
{ 512 ,256 ,0 ,1 , 0xffffffff , 1.0 ,0.0 },
{ 256 ,512 ,0 ,1 , 0xffffffff , 0.0 ,1.0 },
{ 512 ,512 ,0 ,1 , 0xffffffff , 1.0 ,1.0 },
};
StCustomVertex2 pVertex3[4] = {
//rect3
{ 0 ,256 ,0 ,1 , 0xffffffff , 0 ,0 },
{ 256 ,256 ,0 ,1 , 0xffffffff , 1.0 ,0.0 },
{ 0 ,512 ,0 ,1 , 0xffffffff , 0.0 ,1.0 },
{ 256 ,512 ,0 ,1 , 0xffffffff , 1.0 ,1.0 },
};
glActiveTexture( GL_TEXTURE0 + 0 );
//--------------------------------------------------
//src draw to "render texture"
//--------------------------------------------------
{
//adjust screensize to Texture size
glViewport( 0, 0, TextureWidth , TextureHeight );
glBindFramebuffer( GL_FRAMEBUFFER, OpenGL.s_offscreen_fbo );
//clear "render texture"
glClearColor( 0.0f, 1.0f, 0.0f, 1.f ); //(green)
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture( GL_TEXTURE_2D, OpenGL.m_sTexIndex[0] ); //use "noise texture"
drawPrim( pVertex1 , TextureWidth , TextureHeight );
}
//--------------------------------------------------
//"render texture" draw to "frame buffer"
//--------------------------------------------------
{
//adjust screensize to Window size
glViewport(0, 0, WINDOW_WIDTH,WINDOW_HEIGHT );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glBindTexture( GL_TEXTURE_2D, OpenGL.m_sTexIndex[1] ); //use "render texture"
drawPrim( pVertex2 , WINDOW_WIDTH , WINDOW_HEIGHT );
}
//--------------------------------------------------
//capture "rgba data" from "render texture"
//--------------------------------------------------
glBindFramebuffer( GL_FRAMEBUFFER, OpenGL.s_offscreen_fbo );
// glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels( 0, 0, TextureWidth, TextureHeight, GL_RGBA, GL_UNSIGNED_BYTE, texImage3 );
//make "capture texture" from "rgba data"
glBindTexture( GL_TEXTURE_2D, OpenGL.m_sTexIndex[2] );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage3 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); //<--- important!
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
//draw "capture texture" to "frame buffer"
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
drawPrim( pVertex3 , WINDOW_WIDTH , WINDOW_HEIGHT );
}
void drawPrim( StCustomVertex2 *pVertex , int width , int height )
{
//----------------------------------------------------------------------
//render primitive
//div rect to triangle x2.
//----------------------------------------------------------------------
//vtx (-1,+1) - (+1,+1)
// (-1,-1) - (+1,-1)
//uvs ( 0,+1) - (+1,+1)
// ( 0, 0) - (+1, 0)
//----------------------------------------------------------------------
float vtx[] = {
//Vertices
pVertex[0].x / (width / 2) - 1.0f, -(pVertex[0].y / (height / 2) - 1.0f) , 0.0f,
pVertex[1].x / (width / 2) - 1.0f, -(pVertex[1].y / (height / 2) - 1.0f) , 0.0f,
pVertex[2].x / (width / 2) - 1.0f, -(pVertex[2].y / (height / 2) - 1.0f) , 0.0f,
pVertex[2].x / (width / 2) - 1.0f, -(pVertex[2].y / (height / 2) - 1.0f) , 0.0f,
pVertex[1].x / (width / 2) - 1.0f, -(pVertex[1].y / (height / 2) - 1.0f) , 0.0f,
pVertex[3].x / (width / 2) - 1.0f, -(pVertex[3].y / (height / 2) - 1.0f) , 0.0f,
};
float uvs[] = {
//UVs
pVertex[0].u , 1.0f-pVertex[0].v,
pVertex[1].u , 1.0f-pVertex[1].v,
pVertex[2].u , 1.0f-pVertex[2].v,
pVertex[2].u , 1.0f-pVertex[2].v,
pVertex[1].u , 1.0f-pVertex[1].v,
pVertex[3].u , 1.0f-pVertex[3].v,
};
GLfloat cols[] = {
//Colors
(int((pVertex[0].argb>>24)&0xff)/255.0f),(int((pVertex[0].argb>>16)&0xff)/255.0f),(int((pVertex[0].argb>>8)&0xff)/255.0f),(int((pVertex[0].argb>>0)&0xff)/255.0f), //1.0 ,1.0 ,1.0 , 1.0,
(int((pVertex[1].argb>>24)&0xff)/255.0f),(int((pVertex[1].argb>>16)&0xff)/255.0f),(int((pVertex[1].argb>>8)&0xff)/255.0f),(int((pVertex[1].argb>>0)&0xff)/255.0f), //1.0 ,1.0 ,1.0 , 1.0,
(int((pVertex[2].argb>>24)&0xff)/255.0f),(int((pVertex[2].argb>>16)&0xff)/255.0f),(int((pVertex[2].argb>>8)&0xff)/255.0f),(int((pVertex[2].argb>>0)&0xff)/255.0f), //1.0 ,1.0 ,1.0 , 1.0,
(int((pVertex[2].argb>>24)&0xff)/255.0f),(int((pVertex[2].argb>>16)&0xff)/255.0f),(int((pVertex[2].argb>>8)&0xff)/255.0f),(int((pVertex[2].argb>>0)&0xff)/255.0f), //1.0 ,1.0 ,1.0 , 1.0,
(int((pVertex[1].argb>>24)&0xff)/255.0f),(int((pVertex[1].argb>>16)&0xff)/255.0f),(int((pVertex[1].argb>>8)&0xff)/255.0f),(int((pVertex[1].argb>>0)&0xff)/255.0f), //1.0 ,1.0 ,1.0 , 1.0,
(int((pVertex[3].argb>>24)&0xff)/255.0f),(int((pVertex[3].argb>>16)&0xff)/255.0f),(int((pVertex[3].argb>>8)&0xff)/255.0f),(int((pVertex[3].argb>>0)&0xff)/255.0f), //1.0 ,1.0 ,1.0 , 1.0,
};
//draw with shader
glEnableVertexAttribArray( 0 );
GLuint position = glGetAttribLocation( OpenGL.shaderProgram, "a_position" );
glVertexAttribPointer( position, 3, GL_FLOAT, GL_FALSE, 0, vtx );
glEnableVertexAttribArray(position);
GLuint texcoord = glGetAttribLocation( OpenGL.shaderProgram, "a_texCoord" );
glVertexAttribPointer( texcoord, 2, GL_FLOAT, GL_FALSE, 0, uvs );
glEnableVertexAttribArray( texcoord );
GLuint color = glGetAttribLocation( OpenGL.shaderProgram, "a_color" );
glVertexAttribPointer( color, 4, GL_FLOAT, GL_FALSE, 0, cols );
glEnableVertexAttribArray( color );
int textureID1;
textureID1 = glGetUniformLocation( OpenGL.shaderProgram, "u_textureID1" );
glUniform1i(textureID1, 0 );
glUseProgram( OpenGL.shaderProgram );
glDrawArrays( GL_TRIANGLES, 0, 6 );
glDisableVertexAttribArray( 0 );
}
**頂点バッファなしで描画する [#ddebc77a]
**頂点バッファありで描画する(VBO) [#x177ce92]
**Indexバッファを使って描画する [#f0657090]