void DynamicStreamApp::createVBForDynamicStream( izanagi::IMemoryAllocator* allocator, izanagi::graph::CGraphicsDevice* device) { m_vbDynamicStream = device->CreateVertexBuffer( sizeof(Vertex), // 描画の際に使われるので、正しい値を設定しておく. 0, // glBufferStorage で確保されるので、この値はゼロにしておく. izanagi::graph::E_GRAPH_RSC_USAGE_DYNAMIC); CALL_GL_API(::glGenBuffers(1, &m_glVB)); m_vbDynamicStream->overrideNativeResource(&m_glVB); CALL_GL_API(::glBindBuffer(GL_ARRAY_BUFFER, m_glVB)); const GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; m_bufferSize = LIST_NUM * sizeof(Vertex) * POINT_NUM; CALL_GL_API(::glBufferStorage( GL_ARRAY_BUFFER, m_bufferSize, NULL, flags)); m_mappedDataPtr = ::glMapBufferRange(GL_ARRAY_BUFFER, 0, m_bufferSize, flags); IZ_ASSERT(m_mappedDataPtr); }
/** * アンロック */ IZ_BOOL CVertexBufferOGL::Unlock(CGraphicsDevice* device) { IZ_ASSERT(s_isLocked); IZ_ASSERT(m_VB > 0); IZ_BOOL isLocked = m_isLocked; if (isLocked) { #if 0 CALL_GL_API(glUnmapBuffer(GL_COPY_WRITE_BUFFER)); CALL_GL_API(glBindBuffer( GL_COPY_WRITE_BUFFER, 0)); #else CALL_GL_API(glUnmapNamedBuffer(m_VB)); #endif m_prevVB = 0; m_isLocked = IZ_FALSE; } s_isLocked = IZ_FALSE; return isLocked; }
static GLuint CreateShader(const char* shaderPath, GLenum type) { FILE* fp = nullptr; fopen_s(&fp, shaderPath, "rt"); assert(fp != nullptr); char program[2048] = { 0 }; fread(program, 1, sizeof(program), fp); CALL_GL_API(auto shader = ::glCreateShader(type)); assert(shader != 0); const char* p = program; const char** pp = &p; CALL_GL_API(::glShaderSource( shader, 1, pp, nullptr)); CALL_GL_API(::glCompileShader(shader)); return shader; }
static void Init() { GLenum result = glewInit(); assert(result == GLEW_OK); auto version = ::glGetString(GL_VERSION); PRINTF("GL Version(%s)\n", version); CALL_GL_API(::glClipControl( GL_LOWER_LEFT, GL_ZERO_TO_ONE)); CALL_GL_API(::glFrontFace(GL_CCW)); CALL_GL_API(::glViewport(0, 0, WIDTH, HEIGHT)); CALL_GL_API(::glDepthRangef(0.0f, 1.0f)); g_vs = CreateShader("shader/vs.glsl", GL_VERTEX_SHADER); g_fs = CreateShader("shader/fs.glsl", GL_FRAGMENT_SHADER); g_program = CreateShaderProgram(g_vs, g_fs); g_tex = CreateTexture(); }
void DynamicStreamApp::RenderDynamicStream(izanagi::graph::CGraphicsDevice* device) { CALL_GL_API(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)); CALL_GL_API(::glEnable(GL_POINT_SPRITE)); device->SetShaderProgram(m_shd); auto& camera = GetCamera(); izanagi::math::SMatrix44 mtxW2C; izanagi::math::SMatrix44::Copy(mtxW2C, camera.GetParam().mtxW2C); IZ_FLOAT pointSize = 100.0f; auto hSize = m_shd->GetHandleByName("size"); m_shd->SetFloat(device, hSize, pointSize); auto hMtxW2C = m_shd->GetHandleByName("mtxW2C"); m_shd->SetMatrixArrayAsVectorArray(device, hMtxW2C, &mtxW2C, 4); device->SetVertexBuffer(0, 0, sizeof(Vertex), m_vbDynamicStream); device->SetVertexDeclaration(m_vd); IZ_UINT offset = 0; IZ_UINT length = LIST_NUM * sizeof(Vertex) * POINT_NUM; // Need to wait for this area to become available. If we've sized things properly, it will always be // available right away. //m_mgrBufferLock.WaitForLockedRange(offset, length); for (IZ_UINT i = 0; i < LIST_NUM; i++) { #ifdef ENABLE_TRHEAD if (m_items[i].isRenderable) { device->DrawPrimitive( izanagi::graph::E_GRAPH_PRIM_TYPE_POINTLIST, m_items[i].offset, POINT_NUM); m_items[i].isRenderable = false; } #else IZ_UINT8* dst = (IZ_UINT8*)m_mappedDataPtr; dst += offset * sizeof(Vertex); memcpy(dst, m_vtx[i], sizeof(m_vtx[i])); device->DrawPrimitive( izanagi::graph::E_GRAPH_PRIM_TYPE_POINTLIST, offset, POINT_NUM); offset += POINT_NUM; #endif } //m_mgrBufferLock.LockRange(offset, length); }
// ロック IZ_BOOL CVertexBufferOGL::Lock( CGraphicsDevice* device, IZ_UINT offset, IZ_UINT size, void** data, IZ_BOOL isReadOnly, IZ_BOOL isDiscard/*= IZ_FALSE*/) { IZ_ASSERT(!s_isLocked); // NOTE // Just only read or write, can't both read and write. IZ_ASSERT(!isReadOnly); IZ_UINT lockSize = (size > 0 ? size : GetSize()); IZ_ASSERT(lockSize + offset <= GetSize()); void* tmp = nullptr; #if 0 CALL_GL_API(::glBindBuffer( GL_COPY_WRITE_BUFFER, m_VB)); CALL_GL_API(tmp = ::glMapBufferRange( GL_COPY_WRITE_BUFFER, offset, lockSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)); IZ_ASSERT(tmp != nullptr); #else CALL_GL_API(tmp = ::glMapNamedBufferRange( m_VB, offset, lockSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)); IZ_ASSERT(tmp != nullptr); #endif *data = tmp; m_isLocked = IZ_TRUE; s_isLocked = IZ_TRUE; return IZ_TRUE; }
static GLuint CreateTexture() { GLuint tex = 0; CALL_GL_API(::glGenTextures(1, &tex)); CALL_GL_API(::glBindTexture(GL_TEXTURE_2D, tex)); CALL_GL_API(::glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL)); CALL_GL_API(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); CALL_GL_API(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); CALL_GL_API(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)); CALL_GL_API(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)); CALL_GL_API(::glBindTexture(GL_TEXTURE_2D, 0)); return tex; }
/** * アンロック */ IZ_BOOL CVertexBufferGLES2::Unlock(CGraphicsDevice* device) { IZ_ASSERT(m_VB > 0); IZ_BOOL isLocked = (m_LockSize > 0); if (isLocked) { CVertexBuffer* curVB = m_Device->GetRenderState().curVB[0]; if (curVB != this) { // もしかしたら Initialize(device); } VtxBufferOperator vbOp(device, m_VB); IZ_UINT8* tmp = reinterpret_cast<IZ_UINT8*>(m_TemporaryData); tmp += m_LockOffset; CALL_GL_API(::glBufferSubData( GL_ARRAY_BUFFER, m_LockOffset, m_LockSize, tmp)); // 元に戻す if (curVB != this) { if (curVB == IZ_NULL) { CALL_GL_API(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } else { CALL_GL_API(::glBindBuffer( GL_ARRAY_BUFFER, ((CVertexBufferGLES2*)curVB)->m_VB)); } } m_LockOffset = 0; m_LockSize = 0; } if (!IsDynamic()) { FREE(m_Allocator, m_TemporaryData); m_TemporaryData = IZ_NULL; m_AllocSize = 0; } return isLocked; }
IZ_BOOL CTextureOGL::Write( IZ_UINT level, void* data, IZ_UINT x, IZ_UINT y, IZ_UINT width, IZ_UINT height) { IZ_ASSERT(m_Texture != 0); // Check not locked. IZ_ASSERT(m_LockedSize == 0); IZ_ASSERT(x < width); IZ_ASSERT(y < height); IZ_UINT w = GetWidth(level); IZ_UINT h = GetHeight(level); VRETURN(width <= w); VRETURN(height <= h); CALL_GL_API(::glTextureSubImage2D( m_Texture, level, x, y, width, height, m_GLFormat, m_GLType, data)); return IZ_TRUE; }
static GLuint CreateShaderProgram(GLuint vs, GLuint fs) { auto program = ::glCreateProgram(); assert(program != 0); CALL_GL_API(::glAttachShader(program, vs)); CALL_GL_API(::glAttachShader(program, fs)); CALL_GL_API(::glLinkProgram(program)); GLint isLinked = 0; CALL_GL_API(::glGetProgramiv(program, GL_LINK_STATUS, &isLinked)); assert(isLinked != 0); return program; }
VtxBufferOperator(CGraphicsDevice* device, GLuint targetVB) { auto vb = (CVertexBufferGLES2*)device->GetRenderState().curVB[0]; m_prevVB = (vb != IZ_NULL ? vb->m_VB : 0); CALL_GL_API(::glBindBuffer(GL_ARRAY_BUFFER, targetVB)); }
// デストラクタ CVertexBufferGLES2::~CVertexBufferGLES2() { SAFE_RELEASE(m_Device); if (m_VB > 0) { CALL_GL_API(::glDeleteBuffers(1, &m_VB)); } FREE(m_Allocator, m_TemporaryData); }
void DynamicStreamApp::RenderMapUnmap(izanagi::graph::CGraphicsDevice* device) { CALL_GL_API(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)); CALL_GL_API(::glEnable(GL_POINT_SPRITE)); device->SetShaderProgram(m_shd); auto& camera = GetCamera(); izanagi::math::SMatrix44 mtxW2C; izanagi::math::SMatrix44::Copy(mtxW2C, camera.GetParam().mtxW2C); IZ_FLOAT pointSize = 100.0f; auto hSize = m_shd->GetHandleByName("size"); m_shd->SetFloat(device, hSize, pointSize); auto hMtxW2C = m_shd->GetHandleByName("mtxW2C"); m_shd->SetMatrixArrayAsVectorArray(device, hMtxW2C, &mtxW2C, 4); device->SetVertexBuffer(0, 0, sizeof(Vertex), m_vbMapUnmap); device->SetVertexDeclaration(m_vd); for (IZ_UINT i = 0; i < LIST_NUM; i++) { void* dst = nullptr; m_vbMapUnmap->Lock( device, 0, 0, (void**)&dst, IZ_FALSE); memcpy(dst, m_vtx[i], sizeof(m_vtx[i])); m_vbMapUnmap->Unlock(device); device->DrawPrimitive( izanagi::graph::E_GRAPH_PRIM_TYPE_POINTLIST, 0, POINT_NUM); } }
void CVertexBufferOGL::overrideNativeResource(void* rsc) { GLuint vb = (rsc ? *(GLuint*)rsc : 0); if (vb > 0) { if (m_VB > 0) { CALL_GL_API(::glDeleteBuffers(1, &m_VB)); } } m_VB = vb; }
void DxtEncoder::draw(izanagi::graph::CGraphicsDevice* device) { device->SaveRenderState(); device->SetRenderState( izanagi::graph::E_GRAPH_RS_ZENABLE, IZ_FALSE); device->SetRenderState( izanagi::graph::E_GRAPH_RS_CULLMODE, izanagi::graph::E_GRAPH_CULL_NONE); device->SetShaderProgram(m_shdDraw); { CALL_GL_API(::glActiveTexture(GL_TEXTURE0)); GLuint handle = m_texDxt->GetTexHandle(); CALL_GL_API(::glBindTexture(GL_TEXTURE_2D, handle)); } auto hImage = m_shdDraw->GetHandleByName("image"); auto hMode = m_shdDraw->GetHandleByName("mode"); auto hToSRGB = m_shdDraw->GetHandleByName("to_srgb"); CALL_GL_API(glUniform1i(hImage, 0)); CALL_GL_API(glUniform1i(hMode, 3)); CALL_GL_API(glUniform1i(hToSRGB, 0)); // NOTE // 頂点バッファを使わず全画面に描画する頂点シェーダ. CALL_GL_API(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); device->LoadRenderState(); }
void CVertexBufferGLES2::Initialize(CGraphicsDevice* device) { if (!m_IsInitialized) { VtxBufferOperator vbOp(device, m_VB); GLenum glUsage = (m_CreateType == E_GRAPH_RSC_USAGE_STATIC ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW); CALL_GL_API(::glBufferData( GL_ARRAY_BUFFER, m_Size, NULL, glUsage)); m_IsInitialized = IZ_TRUE; } }
// 解放. void DynamicStreamApp::ReleaseInternal() { #ifdef ENABLE_TRHEAD m_isRunThread = false; if (m_thread.joinable()) { m_thread.join(); } #endif m_vbDynamicStream->overrideNativeResource(nullptr); CALL_GL_API(::glDeleteBuffers(1, &m_glVB)); SAFE_RELEASE(m_vbDynamicStream); SAFE_RELEASE(m_vbMapUnmap); SAFE_RELEASE(m_vd); SAFE_RELEASE(m_vs); SAFE_RELEASE(m_ps); SAFE_RELEASE(m_shd); }
// 本体作成 IZ_BOOL CVertexBufferGLES2::CreateBody( CGraphicsDevice* device, IZ_UINT stride, IZ_UINT vtxNum, E_GRAPH_RSC_USAGE usage) { CALL_GL_API(::glGenBuffers(1, &m_VB)); VRETURN(m_VB > 0); IZ_BOOL ret = (m_VB > 0); GLsizeiptr size = vtxNum * stride; m_Stride = stride; m_VtxNum = vtxNum; m_Size = size; m_CreateType = usage; Initialize(device); return ret; }
IZ_BOOL CVertexBufferGLES2::Disable() { CALL_GL_API(::glDeleteBuffers(1, &m_VB)); return IZ_TRUE; }
~VtxBufferOperator() { CALL_GL_API(::glBindBuffer(GL_ARRAY_BUFFER, m_prevVB)); }
void DxtEncoder::encode( izanagi::graph::CGraphicsDevice* device, izanagi::graph::CTexture* texture) { izanagi::sys::CTimer timer; device->SaveRenderState(); device->SetRenderState( izanagi::graph::E_GRAPH_RS_ZENABLE, IZ_FALSE); // For rendering full screen quad without vertex buffer. device->SetRenderState( izanagi::graph::E_GRAPH_RS_CULLMODE, izanagi::graph::E_GRAPH_CULL_NONE); auto texHandle = m_tex->GetTexHandle(); // Set FBO. CALL_GL_API(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo)); CALL_GL_API(glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texHandle, 0)); GLenum attachedColor[] = { GL_COLOR_ATTACHMENT0, }; CALL_GL_API(::glDrawBuffers(1, attachedColor)); CALL_GL_API(glDisable(GL_FRAMEBUFFER_SRGB)); device->SetShaderProgram(m_shd); { CALL_GL_API(::glActiveTexture(GL_TEXTURE0)); GLuint handle = texture->GetTexHandle(); CALL_GL_API(::glBindTexture(GL_TEXTURE_2D, handle)); } auto hImage = m_shd->GetHandleByName("image"); auto hMode = m_shd->GetHandleByName("mode"); CALL_GL_API(glUniform1i(hImage, 0)); CALL_GL_API(glUniform1i(hMode, 3)); device->SetViewport( izanagi::graph::SViewport(0, 0, m_width/4, m_height/4)); // NOTE // 頂点バッファを使わず全画面に描画する頂点シェーダ. CALL_GL_API(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); #if 1 // Copy to PBO. { timer.Begin(); // NOTE // PBO は STREAM_COPY で作成されている. CALL_GL_API(glReadBuffer(GL_COLOR_ATTACHMENT0)); CALL_GL_API(glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo)); // Copy from GL_COLOR_ATTACHMENT0 to PBO. CALL_GL_API(glReadPixels( 0, 0, m_width / 4, m_height / 4, GL_RGBA_INTEGER, GL_UNSIGNED_INT, 0)); CALL_GL_API(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)); auto time = timer.End(); IZ_PRINTF("ReadToPBO [%f]\n", time); } CALL_GL_API(glBindFramebuffer(GL_FRAMEBUFFER, 0)); // Copy to texture memory. { timer.Begin(); auto texdxt = m_texDxt->GetTexHandle(); CALL_GL_API(glBindTexture(GL_TEXTURE_2D, texdxt)); CALL_GL_API(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo)); // Copy from PBO to texture(DXT5) memory. CALL_GL_API(glCompressedTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, m_width, m_height, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, m_width * m_height, 0)); CALL_GL_API(glBindTexture(GL_TEXTURE_2D, 0)); CALL_GL_API(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); auto time = timer.End(); IZ_PRINTF("CopyToDXT [%f]\n", time); } // Readback to memory. { timer.Begin(); auto texdxt = m_texDxt->GetTexHandle(); CALL_GL_API(glBindTexture(GL_TEXTURE_2D, texdxt)); CALL_GL_API(glGetCompressedTexImage( GL_TEXTURE_2D, 0, m_pixels)); CALL_GL_API(glBindTexture(GL_TEXTURE_2D, 0)); auto time = timer.End(); IZ_PRINTF("ReadToMem [%f]\n", time); } #endif // 元に戻す. device->SetViewport( izanagi::graph::SViewport(0, 0, m_width, m_height)); device->LoadRenderState(); }
void FoveatedRenderingApp::FoveatedRender(izanagi::graph::CGraphicsDevice* device) { izanagi::sample::CSampleCamera& camera = GetCamera(); device->BeginScene( &m_mask, 1, izanagi::graph::E_GRAPH_CLEAR_FLAG_ALL); { // For rendering full screen quad without vertex buffer. device->SetRenderState( izanagi::graph::E_GRAPH_RS_CULLMODE, izanagi::graph::E_GRAPH_CULL_NONE); auto shd = m_shdMakeMask.m_shd; device->SetShaderProgram(shd); auto hInvScr = shd->GetHandleByName("invScreen"); izanagi::math::CVector4 invScr(1.0f / SCREEN_WIDTH, 1.0f / SCREEN_HEIGHT, 0, 0); shd->SetVector(device, hInvScr, invScr); auto hCenter = shd->GetHandleByName("center"); izanagi::math::CVector4 center(SCREEN_WIDTH * 0.5f, SCREEN_HEIGHT * 0.5f, 0, 0); shd->SetVector(device, hCenter, center); CALL_GL_API(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); } device->EndScene(); device->BeginScene( &m_rt, 1, m_depth, izanagi::graph::E_GRAPH_CLEAR_FLAG_ALL); { device->SetTexture(0, m_Img->GetTexture(m_Idx)); device->SetTexture(1, m_mask); auto shd = m_shdDrawCube.m_shd; device->SetShaderProgram(shd); auto hL2W = shd->GetHandleByName("g_mL2W"); shd->SetMatrix(device, hL2W, m_L2W); auto mtxW2C = camera.GetParam().mtxW2C; auto hW2C = shd->GetHandleByName("g_mW2C"); shd->SetMatrix(device, hW2C, mtxW2C); auto hEye = shd->GetHandleByName("g_vEye"); shd->SetVector(device, hEye, camera.GetParam().pos); auto hInvScr = shd->GetHandleByName("invScreen"); izanagi::math::CVector4 invScr(1.0f / SCREEN_WIDTH, 1.0f / SCREEN_HEIGHT, 0, 0); shd->SetVector(device, hInvScr, invScr); auto hCanFoveated = shd->GetHandleByName("canFoveated"); shd->SetBool(device, hCanFoveated, true); m_Cube->Render(device); } device->EndScene(); device->SetRenderState( izanagi::graph::E_GRAPH_RS_ZWRITEENABLE, IZ_FALSE); device->SetRenderState( izanagi::graph::E_GRAPH_RS_ZENABLE, IZ_FALSE); { auto shd = m_shdFilter.m_shd; device->SetShaderProgram(shd); m_rt->SetFilter( izanagi::graph::E_GRAPH_TEX_FILTER_POINT, izanagi::graph::E_GRAPH_TEX_FILTER_POINT, izanagi::graph::E_GRAPH_TEX_FILTER_NONE); m_rt->SetAddress( izanagi::graph::E_GRAPH_TEX_ADDRESS_CLAMP, izanagi::graph::E_GRAPH_TEX_ADDRESS_CLAMP); device->SetTexture(0, m_rt); auto hTex0 = shd->GetHandleByName("s0"); CALL_GL_API(glUniform1i(hTex0, 0)); device->SetTexture(1, m_mask); auto hTex1 = shd->GetHandleByName("s1"); CALL_GL_API(glUniform1i(hTex1, 1)); auto hInvScr = shd->GetHandleByName("invScreen"); izanagi::math::CVector4 invScr(1.0f / SCREEN_WIDTH, 1.0f / SCREEN_HEIGHT, 0, 0); shd->SetVector(device, hInvScr, invScr); CALL_GL_API(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); } }
void display(hitable* world, camera& cam) { CALL_GL_API(::glClearColor(0.0f, 0.5f, 1.0f, 1.0f)); CALL_GL_API(::glClearDepthf(1.0f)); CALL_GL_API(::glClearStencil(0)); CALL_GL_API(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); CALL_GL_API(::glUseProgram(g_program)); GLfloat invScreen[4] = { 1.0f / WIDTH, 1.0f / HEIGHT, 0.0f, 0.0f }; auto hInvScreen = GetHandle(g_program, "invScreen"); CALL_GL_API(::glUniform4fv(hInvScreen, 1, invScreen)); CALL_GL_API(::glActiveTexture(GL_TEXTURE0)); CALL_GL_API(::glBindTexture(GL_TEXTURE_2D, g_tex)); auto hImage = GetHandle(g_program, "image"); CALL_GL_API(glUniform1i(hImage, 0)); float lum = 0.0f; float maxlum = 0.0f; timer time; time.begin(); #ifdef ENABLE_MULTI_THREAD int step = ny / thread_num; int begin = 0; for (int i = 0; i < thread_num; i++) { g_threadData[i].idx = i; g_threadData[i].begin = begin; begin += step; g_threadData[i].end = begin + step; g_threadData[i].end = (g_threadData[i].end > HEIGHT ? HEIGHT : g_threadData[i].end); g_threadData[i].world = world; g_threadData[i].cam = &cam; g_eventWorker[i].Set(); g_threads[i].Start([&](void* userData, bool running) { ThreadData* data = (ThreadData*)userData; onDisplay(data, running); }, &g_threadData[i]); } for (int i = 0; i < thread_num; i++) { g_eventMain[i].Wait(); g_eventMain[i].Reset(); } for (int i = 0; i < thread_num; i++) { lum += g_sumY[i]; maxlum = math::CMath::Max(g_maxLum[i], maxlum); } lum /= thread_num; #else onDisplay(world, &cam, 0, 0, ny, true); lum = g_sumY[0]; maxlum = g_maxLum[0]; #endif auto elapsed = time.end(); printf("Elapsed[%f]\n", elapsed); static uint8_t s_color[HEIGHT][WIDTH][4]; static float fMiddleGrey = 0.18f; static const vec3 RGB2Y(+0.29900f, +0.58700f, +0.11400f); static const vec3 RGB2Cb(-0.16874f, -0.33126f, +0.50000f); static const vec3 RGB2Cr(+0.50000f, -0.41869f, -0.08131f); static const vec3 YCbCr2R(+1.00000f, +0.00000f, +1.40200f); static const vec3 YCbCr2G(+1.00000f, -0.34414f, -0.71414f); static const vec3 YCbCr2B(+1.00000f, +1.77200f, +0.00000f); // NOTE // HDR // http://t-pot.com/program/123_ToneMapping/index.html float coeff = 0.18f / exp(lum); float l_max = coeff * maxlum; for (int j = 0; j < ny; j++) { for (int i = 0; i < nx; i++) { #if 1 vec3 col(g_color[j][i][0], g_color[j][i][1], g_color[j][i][2]); float y = dot(RGB2Y, col); float cb = dot(RGB2Cb, col); float cr = dot(RGB2Cr, col); y = coeff * y; y = y * (1.0f + y / (l_max * l_max)) / (1.0f + y); vec3 ycbcr(y, cb, cr); float r = dot(YCbCr2R, ycbcr); float g = dot(YCbCr2G, ycbcr); float b = dot(YCbCr2B, ycbcr); int ir = int(255.9f * r); int ig = int(255.9f * g); int ib = int(255.9f * b); s_color[j][i][0] = math::CMath::Clamp(ir, 0, 255); s_color[j][i][1] = math::CMath::Clamp(ig, 0, 255); s_color[j][i][2] = math::CMath::Clamp(ib, 0, 255); #else auto r = 2 * int(255.9f * g_color[j][i][0] * div[0]); auto g = 2 * int(255.9f * g_color[j][i][1] * div[1]); auto b = 2 * int(255.9f * g_color[j][i][2] * div[2]); s_color[j][i][0] = math::CMath::Clamp(r, 0, 255); s_color[j][i][1] = math::CMath::Clamp(g, 0, 255); s_color[j][i][2] = math::CMath::Clamp(b, 0, 255); #endif } } CALL_GL_API(::glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, s_color)); CALL_GL_API(::glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); }
IZ_BOOL DxtEncoder::init( izanagi::IMemoryAllocator* allocator, izanagi::graph::CGraphicsDevice* device, IZ_UINT width, IZ_UINT height, const char* vtxShader, const char* dxtShader, const char* pixelShader) { m_width = width; m_height = height; char* buf = nullptr; IZ_UINT allocatedSize = 0; { izanagi::CFileInputStream in; VRETURN(in.Open(dxtShader)); allocatedSize = in.GetSize(); buf = (char*)ALLOC(allocator, allocatedSize); in.Read(buf, 0, allocatedSize); buf[allocatedSize] = 0; m_dxt = device->CreatePixelShader(buf); VRETURN(m_dxt); } { izanagi::CFileInputStream in; VRETURN(in.Open(vtxShader)); auto size = in.GetSize(); IZ_ASSERT(allocatedSize >= size); in.Read(buf, 0, size); buf[size] = 0; m_vs = device->CreateVertexShader(buf); VRETURN(m_vs); } { izanagi::CFileInputStream in; VRETURN(in.Open(pixelShader)); auto size = in.GetSize(); IZ_ASSERT(allocatedSize >= size); in.Read(buf, 0, size); buf[size] = 0; m_ps = device->CreatePixelShader(buf); VRETURN(m_ps); } FREE(allocator, buf); { m_shd = device->CreateShaderProgram(); VRETURN(m_shd); VRETURN(m_shd->AttachVertexShader(m_vs)); VRETURN(m_shd->AttachPixelShader(m_dxt)); } { m_shdDraw = device->CreateShaderProgram(); VRETURN(m_shdDraw); VRETURN(m_shdDraw->AttachVertexShader(m_vs)); VRETURN(m_shdDraw->AttachPixelShader(m_ps)); } { // NOTE // DXTは 4x4 ブロックで、128bit/block. // GL_RGBA32UI は 128bit/texel. // すると、1texel が DXTのブロックのサイズと同じになるので、fragment shaderの1pixel出力がそのままDXTの1ブロックになる. m_tex = device->CreateTexture( width / 4, height / 4, 1, izanagi::graph::E_GRAPH_PIXEL_FMT_RGBA32UI, izanagi::graph::E_GRAPH_RSC_USAGE_STATIC); VRETURN(m_tex); CALL_GL_API(glGenFramebuffers(1, &m_fbo)); glGenBuffers(1, &m_pbo); glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo); glBufferData(GL_PIXEL_PACK_BUFFER, width * height, 0, GL_STREAM_COPY); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); m_texDxt = device->CreateTexture( width, height, 1, izanagi::graph::E_GRAPH_PIXEL_FMT_DXT5, izanagi::graph::E_GRAPH_RSC_USAGE_STATIC); VRETURN(m_tex); } { m_allocator = allocator; // NOTE // RGBA : w * h * 4; // DXT5 : RGBA / 4 = (w * h * 4) / 4 = w * h auto size = width * height; m_pixels = ALLOC_ZERO(m_allocator, size); } return IZ_TRUE; }
void display(hitable* world, camera& cam) { CALL_GL_API(::glClearColor(0.0f, 0.5f, 1.0f, 1.0f)); CALL_GL_API(::glClearDepthf(1.0f)); CALL_GL_API(::glClearStencil(0)); CALL_GL_API(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); CALL_GL_API(::glUseProgram(g_program)); GLfloat invScreen[4] = { 1.0f / WIDTH, 1.0f / HEIGHT, 0.0f, 0.0f }; auto hInvScreen = GetHandle(g_program, "invScreen"); CALL_GL_API(::glUniform4fv(hInvScreen, 1, invScreen)); CALL_GL_API(::glActiveTexture(GL_TEXTURE0)); CALL_GL_API(::glBindTexture(GL_TEXTURE_2D, g_tex)); auto hImage = GetHandle(g_program, "image"); CALL_GL_API(glUniform1i(hImage, 0)); { int ns = 10; #pragma omp for for (int j = ny - 1; j >= 0; j--) { for (int i = 0; i < nx; i++) { vec3 col(0, 0, 0); for (int s = 0; s < ns; s++) { float u = float(i + drand48()) / float(nx); float v = float(j + drand48()) / float(ny); ray r = cam.get_ray(u, v); col += color(r, world, 0); } col /= float(ns); col = vec3( sqrt(col[0]), sqrt(col[1]), sqrt(col[2])); g_color[j][i][0] = int(255.99*col[0]); g_color[j][i][1] = int(255.99*col[1]); g_color[j][i][2] = int(255.99*col[2]); g_color[j][i][3] = 255; } } } CALL_GL_API(::glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, g_color)); CALL_GL_API(::glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); }