bool DeferredRenderer::Init(int w, int h) { SR_ASSERT(geometry_uber_shader_.get() == NULL); SR_ASSERT(gbuffer_.get() == NULL); SR_ASSERT(final_result_fb_.get() == NULL); gbuffer_ = move(unique_ptr<GBuffer>(new GBuffer())); gbuffer_->Init(w, h); LOGI("Deferred Renderer :: Geomerty Shader"); const char *vert_file = "shader/deferred/deferred_geometry.vs"; const char *frag_file = "shader/deferred/deferred_geometry.fs"; unsigned int flag = 0; //flag |= kMaterialAmbient; //디퍼드는 객체별 ambient가 먹히지 않는다(속성을 따로 저장하지 않아서) flag |= kMaterialDiffuse; flag |= kMaterialSpecular; flag |= kMaterialDiffuseMap; flag |= kMaterialSpecularMap; //normal map flag |= kMaterialNormalMap; geometry_uber_shader_.reset(new UberShader()); geometry_uber_shader_->InitWithFile(vert_file, frag_file, flag); //최종결과 final_result_fb_.reset(new FrameBuffer()); final_result_fb_->Init(w, h); return true; }
bool RPSEvent::operator<(const RPSEvent &o) const { SR_ASSERT(o.value != kNone); SR_ASSERT(this->value != kNone); if(o == winEvent()) { return true; } return false; }
Component::Component(int w, int h, const std::string &name) : smgr_(Lib::smgr->createNewSceneManager(false)), rtSize_(w, h), rt_(Lib::driver->addRenderTargetTexture(core::dimension2d<u32>(w, h), name.c_str())), bgColor_(0, 0, 0, 255) { SR_ASSERT(w > 0); SR_ASSERT(h > 0); }
void DoubleStackAllocator::UpperFree(void *ptr) { //data가 stack의 범위에 존재하는 메모리 좌표인가? SR_ASSERT((uchar*)upper_ <= ptr); SR_ASSERT((uchar*)data_ + stack_size_ > ptr); StackAllocHeader *header = reinterpret_cast<StackAllocHeader*>((uchar*)ptr - sizeof(StackAllocHeader)); int alloc_size = header->alloc_size; upper_ += (sizeof(StackAllocHeader) + alloc_size); }
TestComp::TestComp() : Component(512, 512, "RTT1") { this->setBackgroundColor(video::SColor(0, 0, 128, 128)); const char *md2file = "ext/irrlicht/media/faerie.md2"; const char *texfile = "ext/irrlicht/media/faerie2.bmp"; scene::IAnimatedMeshSceneNode* fairy = getSceneMgr()->addAnimatedMeshSceneNode( Lib::smgr->getMesh(md2file)); SR_ASSERT(fairy != nullptr); fairy->setMaterialTexture(0, Lib::driver->getTexture(texfile)); // set diffuse texture fairy->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting fairy->getMaterial(0).Shininess = 20.0f; // set size of specular highlights fairy->setPosition(core::vector3df(-10,0,-100)); fairy->setMD2Animation(scene::EMAT_STAND); // add white light getSceneMgr()->addLightSceneNode(0, core::vector3df(-15,5,-105), video::SColorf(1.0f, 1.0f, 1.0f)); // set ambient light getSceneMgr()->setAmbientLight(video::SColor(0,60,60,60)); // add fixed camera getSceneMgr()->addCameraSceneNode(0, core::vector3df(10,10,-80), core::vector3df(-10,10,-100)); }
void DoubleStackAllocator::LowerFree(void *ptr) { //data가 stack의 범위에 존재하는 메모리 좌표인가? SR_ASSERT((uchar*)data_ <= ptr); SR_ASSERT((uchar*)lower_ > ptr); StackAllocHeader *header = reinterpret_cast<StackAllocHeader*>((uchar*)ptr - sizeof(StackAllocHeader)); int alloc_size = header->alloc_size; //가장마지막에 할당한것을 해제한다면 top와 할당크기가 연관되어잇다. //그렇지 않다면 top가 올바르지 않을것이다 int expected_alloc_size = (uchar*)lower_ - (uchar*)ptr; if(expected_alloc_size == alloc_size) { lower_ -= (sizeof(StackAllocHeader) + alloc_size); } else { SR_ASSERT(!"stack break?"); } }
WireCubeFactory::WireCubeFactory(float width, float height, float depth) : width_(width), height_(height), depth_(depth) { SR_ASSERT(width > 0 && height > 0 && depth > 0); }
void DeferredRenderer::DrawDirectionalLight(const Light &light) { SR_ASSERT(light.type == kLightDirection); //동적 라이팅중에서 구조가 가장 간단한 방향으로 뱉어지는 빛이다. 이것의 경우 //그냥 화면 전체에 대해서 2d로 잘 적용하면 된다 Device *device = Device::GetInstance(); RenderState &render_state = device->render_state(); Shader &shader = directional_shader(); render_state.UseShader(shader); //빛 계산에 쓰이는 공용 속성 설정 SetCommonLightUniform(shader, light); //방향성빛은 방향만 잇으니까 행렬의 3*3만 쓴다 mat3 model_mat(render_state.model_mat()); mat3 light_mat(model_mat); vec3 light_target_pos(light.dir); vec3 viewspace_light_target_pos(light_mat * light_target_pos); vec3 light_dir = normalize(viewspace_light_target_pos); //빛 방향을 디버깅을 위해서 출력하기 //Draw2DManager *draw_2d_mgr = device->draw_2d(); //char light_dir_buf[128]; //sprintf(light_dir_buf, "LightDir:%.4f, %.4f, %.4f", light_dir.x, light_dir.y, light_dir.z); //draw_2d_mgr->AddString(vec2(0, 100), light_dir_buf, Color4ub::Red(), 1.0f); shader.SetUniformVector("u_lightDir", light_dir); SetCommonLightQuadDraw(shader); }
void PrimitiveMeshHelper::PointCube(float width, float height, float depth) { SR_ASSERT(width > 0 && height > 0 && depth > 0); width = width/2; height = height/2; depth = depth/2; vec3 v0(-width, height, -depth); vec3 v1(width, height, -depth); vec3 v2(-width, height, depth); vec3 v3(width, height, depth); vec3 v4(-width, -height, -depth); vec3 v5(width, -height, -depth); vec3 v6(-width, -height, depth); vec3 v7(width, -height, depth); vector<vec3> pos_list(8); pos_list[0] = v0; pos_list[1] = v1; pos_list[2] = v2; pos_list[3] = v3; pos_list[4] = v4; pos_list[5] = v5; pos_list[6] = v6; pos_list[7] = v7; DrawCmdData<Vertex> cmd; cmd.draw_mode = kDrawPoints; for(size_t i = 0 ; i < pos_list.size() ; ++i) { Vertex vert; vert.set_pos(pos_list[i]); cmd.vertex_list.push_back(vert); } this->cmd_list_->push_back(cmd); }
Shader &UberShader::Load(uint flag) { SR_ASSERT(orig_vert_src_.empty() == false && "not initialized yet"); SR_ASSERT(orig_frag_src_.empty() == false && "not initialized yet"); //shader마다 허용 가능한 플래그가 약간 다르다 //요청한것에 대해서 미리 검사하기 if((~avail_mask_ & flag) != 0) { //LOGW("사용할수 없는 flag를 활성화 햇음. 자동 무시"); flag = flag & avail_mask_; } auto found = prog_dict_.find(flag); if(found != prog_dict_.end()) { return found->second; } //없으면 적절히 생성하기 vector<const char*> vert_src_list; vector<const char*> frag_src_list; const int enable_count = sizeof(enable_define_list) / sizeof(enable_define_list[0]); const int disable_count = sizeof(disable_define_list) / sizeof(disable_define_list[0]); SR_STATIC_ASSERT(enable_count == disable_count, "must same size"); for(int i = 0 ; i < enable_count ; i++) { unsigned int mask = 1 << i; if((flag & mask) == mask) { vert_src_list.push_back(enable_define_list[i]); frag_src_list.push_back(enable_define_list[i]); } else { vert_src_list.push_back(disable_define_list[i]); frag_src_list.push_back(disable_define_list[i]); } } vert_src_list.push_back(orig_vert_src_.c_str()); frag_src_list.push_back(orig_frag_src_.c_str()); //쉐이더 프로그램 적절히 생성 LOGI("UberShader Load :: %d", flag); Shader shader_prog; shader_prog.Init(vert_src_list, frag_src_list); prog_dict_[flag] = shader_prog; return prog_dict_[flag]; }
const std::string &DeferredRenderer::light_vert_src() { if(light_vert_src_.empty()) { const char *vert_file = "shader/deferred/deferred_light.vs"; string vert_path = Filesystem::GetAppPath(vert_file); MemoryFile mem_file(vert_path); bool opened = mem_file.Open(); SR_ASSERT(opened == true); const char *src = (const char*)(mem_file.start); light_vert_src_ = src; mem_file.Close(); } return light_vert_src_; }
static bool Load(Image *img, ImageDesc *desc, uchar *data, int data_size) { //lodepng를 기반으로 적절히 로딩하기 SR_ASSERT(data != NULL); SR_ASSERT(data_size > 0); img->image_data_.clear(); LodePNG::Decoder decoder; decoder.decode(img->image_data(), data, data_size); if(decoder.hasError()) { return false; } else { desc->width = decoder.getWidth(); desc->height = decoder.getHeight(); desc->bit_depth = decoder.getInfoPng().color.bitDepth; desc->bpp = decoder.getBpp(); desc->color_channels = decoder.getChannels(); desc->is_grayscale = decoder.isGreyscaleType() > 0 ? true : false; desc->is_alpha = decoder.isAlphaType() > 0 ? true : false; return true; } }
void* DoubleStackAllocator::UpperMalloc(size_t x) { int alloc_size = x + GetAllocHeaderSize(); if(upper_ - lower_ < alloc_size) { SR_ASSERT(!"cannot alloc, more big stack required"); return NULL; } uchar *raw_ptr = upper_ - (alloc_size + 1); upper_ -= alloc_size; StackAllocHeader *header = reinterpret_cast<StackAllocHeader*>(raw_ptr); header->alloc_size = x; uchar *ptr = raw_ptr + GetAllocHeaderSize(); return ptr; }
void DeferredRenderer::DrawLight(const Light &light) { switch(light.type) { case kLightDirection: DrawDirectionalLight(light); break; case kLightPoint: DrawPointLight(light); break; case kLightSpotLight: DrawSpotLight(light); break; default: SR_ASSERT(!"not valid"); } }
void* DoubleStackAllocator::LowerMalloc(size_t x) { //stack할당자와 다른것은 할당후 upper에 닿는지 확인해야한다는 점이다 int alloc_size = x + GetAllocHeaderSize(); if(upper_ - lower_ < alloc_size) { SR_ASSERT(!"cannot alloc, more big stack required"); return NULL; } uchar *raw_ptr = lower_; StackAllocHeader *header = reinterpret_cast<StackAllocHeader*>(raw_ptr); header->alloc_size = x; uchar *ptr = raw_ptr + GetAllocHeaderSize(); lower_ += alloc_size; return ptr; }
const std::string &DeferredRenderer::light_frag_src() { if(light_frag_src_.empty()) { const char *frag_file = "shader/deferred/deferred_light.fs"; string frag_path = Filesystem::GetAppPath(frag_file); MemoryFile mem_file(frag_path); bool opened = mem_file.Open(); SR_ASSERT(opened == true); const char *src = (const char*)(mem_file.start); const std::string &light_model_src = Light::GetLightModelFragSrc(); light_frag_src_ = light_model_src; light_frag_src_ += src; mem_file.Close(); } return light_frag_src_; }
static bool Load(Image *img, ImageDesc *desc, uchar *data, int data_size) { //귀찮은 관계로 soil에 떠넘기자 //압축된거같은 데이터에서 쌩 데이터로 떠내기 int width, height, channels; unsigned char *raw_img = SOIL_load_image_from_memory( data, data_size, &width, &height, &channels, SOIL_LOAD_AUTO ); if(raw_img == nullptr) { return false; } img->image_data_.resize(width * height * channels * sizeof(uchar)); memcpy(img->image_data_.data(), raw_img, img->image_data_.size() * sizeof(uchar)); SOIL_free_image_data(raw_img); //텍스쳐에서 얻어낸 속성을 적절히 재가공 desc->width = width; desc->height = height; desc->bit_depth = 8; //? desc->bpp = 8 * channels; desc->color_channels = channels; switch(channels) { case SOIL_LOAD_L: desc->is_grayscale = true; desc->is_alpha = false; break; case SOIL_LOAD_LA: desc->is_grayscale = true; desc->is_alpha = true; break; case SOIL_LOAD_RGB: desc->is_grayscale = false; desc->is_alpha = false; break; case SOIL_LOAD_RGBA: desc->is_grayscale = false; desc->is_alpha = true; break; default: SR_ASSERT(!"do not reach"); break; } return true; }
RPSEvent RPSEvent::loseEvent() const { int other = 0; switch(value) { case kRock: other = kScissor; break; case kPaper: other = kRock; break; case kScissor: other = kPaper; break; default: SR_ASSERT(!"do not reach"); } return RPSEvent(other); }
void PrimitiveMeshHelper::WireCube(float width, float height, float depth) { SR_ASSERT(width > 0 && height > 0 && depth > 0); width = width/2; height = height/2; depth = depth/2; vec3 v0(-width, height, -depth); vec3 v1(width, height, -depth); vec3 v2(-width, height, depth); vec3 v3(width, height, depth); vec3 v4(-width, -height, -depth); vec3 v5(width, -height, -depth); vec3 v6(-width, -height, depth); vec3 v7(width, -height, depth); vector<vec3> pos_list(8); pos_list[0] = v0; pos_list[1] = v1; pos_list[2] = v2; pos_list[3] = v3; pos_list[4] = v4; pos_list[5] = v5; pos_list[6] = v6; pos_list[7] = v7; DrawCmdData<Vertex> cmd; cmd.draw_mode = kDrawLines; for(size_t i = 0 ; i < pos_list.size() ; ++i) { Vertex vert; vert.set_pos(pos_list[i]); cmd.vertex_list.push_back(vert); } //GL_LINES용 index list std::array<GLushort, 24> index_list = { 0,1, 1,3, 2,3, 0,2, 4,5, 5,7, 6,7, 4,6, 0,4, 1,5, 2,6, 3,7 }; cmd.index_list.resize(index_list.size()); copy(index_list.begin(), index_list.end(), cmd.index_list.begin()); this->cmd_list_->push_back(cmd); }
void *StackAllocator::Malloc(size_t x) { int alloc_size = x + sizeof(StackAllocHeader); //할당 가능한 크기가 x보다 작아야 할당 가능 int curr_allocated_size = top_ - data_; int avail_alloc_size = stack_size_ - curr_allocated_size; if(avail_alloc_size < alloc_size) { SR_ASSERT(!"cannot alloc, more big stack required"); return NULL; } uchar *raw_data = top_; top_ += alloc_size; StackAllocHeader *header = reinterpret_cast<StackAllocHeader*>(raw_data); header->alloc_size = x; uchar *ptr = (uchar*)raw_data + sizeof(StackAllocHeader); return ptr; }
ImageDesc Texture::CreateImageDesc(int w, int h, TexFormatType format) { ImageDesc desc; desc.width = w; desc.height = h; desc.bit_depth = 32; switch(format) { case kTexFormatAlpha: desc.bpp = 8; desc.color_channels = 1; desc.is_grayscale = false; desc.is_alpha = true; break; case kTexFormatLumiance: desc.bpp = 8; desc.color_channels = 1; desc.is_grayscale = true; desc.is_alpha = false; break; case kTexFormatLumianceAlpha: desc.bpp = 16; desc.color_channels = 2; desc.is_grayscale = true; desc.is_alpha = true; break; case kTexFormatRGB: desc.bpp = 24; desc.color_channels = 3; desc.is_grayscale = false; desc.is_alpha = false; break; case kTexFormatRGBA: desc.bpp = 32; desc.color_channels = 4; desc.is_grayscale = false; desc.is_alpha = true; break; default: SR_ASSERT(!"not valid tex format"); } return desc; }
bool MemoryFile::Open() { int flag = O_RDONLY; #if SR_WIN flag |= O_BINARY; #endif int fd = _open(filepath_, flag); SR_ASSERT(fd != -1 && "file is not exist"); if (fd == -1) { return false; } int length = Filesystem::GetFileSize(fd); start = (uchar*)SR_MALLOC(length + 1); data = start; _read(fd, start, length); curr = start; end = curr + length; *end = '\0'; _close(fd); return true; }
float distance_levenshtein(struct sr_thread *thread1, struct sr_thread *thread2, bool transposition) { assert(thread1->type == thread2->type); int frame_count1 = sr_thread_frame_count(thread1); int frame_count2 = sr_thread_frame_count(thread2); int max_frame_count = frame_count2; if (max_frame_count < frame_count1) max_frame_count = frame_count1; /* Avoid division by zero in case we get two empty threads */ if (max_frame_count == 0) return 0.0; int m = frame_count1 + 1; int n = frame_count2 + 1; // store only two last rows and columns instead of whole 2D array SR_ASSERT(n <= SIZE_MAX - 1); SR_ASSERT(m <= SIZE_MAX - (n + 1)); int *dist = sr_malloc_array(sizeof(int), m + n + 1); int *dist1 = sr_malloc_array(sizeof(int), m + n + 1); // first row and column having distance equal to their position for (int i = m; i > 0; --i) dist[m - i] = i; for (int i = 0; i <= n; ++i) dist[m + i] = i; struct sr_frame *curr_frame2 = sr_thread_frames(thread2); struct sr_frame *prev_frame = NULL; struct sr_frame *prev_frame2 = NULL; for (int j = 1; curr_frame2; ++j) { struct sr_frame *curr_frame = sr_thread_frames(thread1); for (int i = 1; curr_frame; ++i) { int l = m + j - i; int dist2 = dist1[l]; dist1[l] = dist[l]; int cost; /*similar characters have distance equal to the previous one diagonally, "??" functions aren't taken as similar */ if (0 == sr_frame_cmp_distance(curr_frame, curr_frame2)) cost = 0; else { // different ones takes the lowest value of all // previous distances cost = 1; dist[l] += 1; if (dist[l] > dist[l - 1] + 1) dist[l] = dist[l - 1] + 1; if (dist[l] > dist[l + 1] + 1) dist[l] = dist[l + 1] + 1; } /*checking for transposition of two characters in both ways taking into account that "??" functions are not similar*/ if (transposition && (i >= 2 && j >= 2 && dist[l] > dist2 + cost && 0 == sr_frame_cmp_distance(curr_frame, prev_frame2) && 0 == sr_frame_cmp_distance(prev_frame, curr_frame2))) { dist[l] = dist2 + cost; } prev_frame = curr_frame; curr_frame = sr_frame_next(curr_frame); } prev_frame2 = curr_frame2; curr_frame2 = sr_frame_next(curr_frame2); } int result = dist[n]; free(dist); free(dist1); return (float)result / max_frame_count; }
void PrimitiveMeshHelper::WirePlane(float half_size, float grid_size) { DrawCmdData<Vertex> cmd; cmd.draw_mode = kDrawLines; VertexList &vert_list = cmd.vertex_list; int grid_range = (int)(half_size / grid_size); //left line(-half_size, 0, half_size) ~ (-half_size, 0, -half_size) //right line(+half_size, 0, half_size) ~ (+half_size, 0, -half_size) //front line(-half_size, 0, +half_size) ~ (+half_size, 0, +half_size) //back line(-half_size, 0, -half_size) ~ (+half_size, 0, -half_size) enum { kLeft = 0, kRight, kFront, kBack }; //([0], 0, [1]) ~ ([2], 0, [3]) float xz_axis_mark[][4] = { { -1, -1, -1, +1 }, { +1, -1, +1, +1 }, { -1, +1, +1, +1 }, { -1, -1, +1, -1 }, }; for(int axis_idx = 0 ; axis_idx < 4 ; ++axis_idx) { int line_vert_size = grid_range * 2 + 1; for(int i = 0 ; i < line_vert_size ; ++i) { int start_index = line_vert_size * axis_idx; int vert_idx = start_index + i; float left_x = xz_axis_mark[axis_idx][0] * half_size; float right_x = xz_axis_mark[axis_idx][2] * half_size; float front_z = xz_axis_mark[axis_idx][3] * half_size; float back_z = xz_axis_mark[axis_idx][1] * half_size; SR_ASSERT(left_x <= right_x); SR_ASSERT(back_z <= front_z); float x, z; float scale = ((float)i / (line_vert_size-1.0f)); if(left_x == right_x) { x = left_x; } else { x = scale * (right_x - left_x) + left_x; } if(front_z == back_z) { z = front_z; } else { z = scale * (front_z - back_z) + back_z; } Vertex vert; vert.pos = vec3(x, 0, z); vert_list.push_back(vert); } } ////////////////////////// std::vector<unsigned short> &index_list = cmd.index_list; //build index list int line_vert_size = grid_range * 2 + 1; index_list.reserve(line_vert_size * 2 * 4); //left .... right를 잇는 선 int left_start_index = line_vert_size * kLeft; int right_start_index = line_vert_size * kRight; for(int i = 0 ; i < line_vert_size ; i++) { index_list.push_back(left_start_index + i); index_list.push_back(right_start_index + i); } //front...back를 잇는 선 int front_start_index = line_vert_size * kFront; int back_start_index = line_vert_size * kBack; for(int i = 0 ; i < line_vert_size ; i++) { index_list.push_back(front_start_index + i); index_list.push_back(back_start_index + i); } this->cmd_list_->push_back(cmd); }
void PrimitiveMeshHelper::SolidCube(float width, float height, float depth) { SR_ASSERT(width > 0 && height > 0 && depth > 0); width = width/2; height = height/2; depth = depth/2; DrawCmdData<Vertex> cmd; cmd.draw_mode = kDrawTriangles; VertexList &vert_list = cmd.vertex_list; std::vector<unsigned short> &index_list = cmd.index_list; //normal { // Front Face int baseIndex = vert_list.size(); vec3 normal(0, 0, +1); vec2 texCoord1(0, 0); vec3 vertex1(-width, -height, depth); vec2 texCoord2(1, 0); vec3 vertex2( width, -height, depth); vec2 texCoord3(1, 1); vec3 vertex3( width, height, depth); vec2 texCoord4(0, 1); vec3 vertex4(-width, height, depth); //add vertex Vertex v1; v1.pos = vertex1; v1.texcoord = texCoord1; v1.normal = normal; Vertex v2; v2.pos = vertex2; v2.texcoord = texCoord2; v2.normal = normal; Vertex v3; v3.pos = vertex3; v3.texcoord = texCoord3; v3.normal = normal; Vertex v4; v4.pos = vertex4; v4.texcoord = texCoord4; v4.normal = normal; vert_list.push_back(v1); vert_list.push_back(v2); vert_list.push_back(v3); vert_list.push_back(v4); //add index index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 1); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 3); } { // Back Face int baseIndex = vert_list.size(); vec3 normal(0, 0, -1); vec2 texCoord1(1, 0); vec3 vertex1(-width, -height, -depth); vec2 texCoord2(1, 1); vec3 vertex2(-width, height, -depth); vec2 texCoord3(0, 1); vec3 vertex3( width, height, -depth); vec2 texCoord4(0, 0); vec3 vertex4( width, -height, -depth); //add vertex Vertex v1; v1.pos = vertex1; v1.texcoord = texCoord1; v1.normal = normal; Vertex v2; v2.pos = vertex2; v2.texcoord = texCoord2; v2.normal = normal; Vertex v3; v3.pos = vertex3; v3.texcoord = texCoord3; v3.normal = normal; Vertex v4; v4.pos = vertex4; v4.texcoord = texCoord4; v4.normal = normal; vert_list.push_back(v1); vert_list.push_back(v2); vert_list.push_back(v3); vert_list.push_back(v4); //add index index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 1); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 3); } { // Top Face int baseIndex = vert_list.size(); vec3 normal(0, 1, 0); vec2 texCoord1(0, 1); vec3 vertex1(-width, height, -depth); vec2 texCoord2(0, 0); vec3 vertex2(-width, height, depth); vec2 texCoord3(1, 0); vec3 vertex3( width, height, depth); vec2 texCoord4(1, 1); vec3 vertex4( width, height, -depth); //add vertex Vertex v1; v1.pos = vertex1; v1.texcoord = texCoord1; v1.normal = normal; Vertex v2; v2.pos = vertex2; v2.texcoord = texCoord2; v2.normal = normal; Vertex v3; v3.pos = vertex3; v3.texcoord = texCoord3; v3.normal = normal; Vertex v4; v4.pos = vertex4; v4.texcoord = texCoord4; v4.normal = normal; vert_list.push_back(v1); vert_list.push_back(v2); vert_list.push_back(v3); vert_list.push_back(v4); //add index index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 1); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 3); } { // Bottom Face int baseIndex = vert_list.size(); vec3 normal(0, -1, 0); vec2 texCoord1(1, 1); vec3 vertex1(-width, -height, -depth); vec2 texCoord2(0, 1); vec3 vertex2( width, -height, -depth); vec2 texCoord3(0, 0); vec3 vertex3( width, -height, depth); vec2 texCoord4(1, 0); vec3 vertex4(-width, -height, depth); //add vertex Vertex v1; v1.pos = vertex1; v1.texcoord = texCoord1; v1.normal = normal; Vertex v2; v2.pos = vertex2; v2.texcoord = texCoord2; v2.normal = normal; Vertex v3; v3.pos = vertex3; v3.texcoord = texCoord3; v3.normal = normal; Vertex v4; v4.pos = vertex4; v4.texcoord = texCoord4; v4.normal = normal; vert_list.push_back(v1); vert_list.push_back(v2); vert_list.push_back(v3); vert_list.push_back(v4); //add index index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 1); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 3); } { // Right face int baseIndex = vert_list.size(); vec3 normal(1, 0, 0); vec2 texCoord1(1, 0); vec3 vertex1(width, -height, -depth); vec2 texCoord2(1, 1); vec3 vertex2(width, height, -depth); vec2 texCoord3(0, 1); vec3 vertex3(width, height, depth); vec2 texCoord4(0, 0); vec3 vertex4(width, -height, depth); //add vertex Vertex v1; v1.pos = vertex1; v1.texcoord = texCoord1; v1.normal = normal; Vertex v2; v2.pos = vertex2; v2.texcoord = texCoord2; v2.normal = normal; Vertex v3; v3.pos = vertex3; v3.texcoord = texCoord3; v3.normal = normal; Vertex v4; v4.pos = vertex4; v4.texcoord = texCoord4; v4.normal = normal; vert_list.push_back(v1); vert_list.push_back(v2); vert_list.push_back(v3); vert_list.push_back(v4); //add index index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 1); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 3); } { // Left Face int baseIndex = vert_list.size(); vec3 normal(0, -1, 0); vec2 texCoord1(0, 0); vec3 vertex1(-width, -height, -depth); vec2 texCoord2(1, 0); vec3 vertex2(-width, -height, depth); vec2 texCoord3(1, 1); vec3 vertex3(-width, height, depth); vec2 texCoord4(0, 1); vec3 vertex4(-width, height, -depth); //add vertex Vertex v1; v1.pos = vertex1; v1.texcoord = texCoord1; v1.normal = normal; Vertex v2; v2.pos = vertex2; v2.texcoord = texCoord2; v2.normal = normal; Vertex v3; v3.pos = vertex3; v3.texcoord = texCoord3; v3.normal = normal; Vertex v4; v4.pos = vertex4; v4.texcoord = texCoord4; v4.normal = normal; vert_list.push_back(v1); vert_list.push_back(v2); vert_list.push_back(v3); vert_list.push_back(v4); //add index index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 1); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 0); index_list.push_back(baseIndex + 2); index_list.push_back(baseIndex + 3); } this->cmd_list_->push_back(cmd); }
void DeferredRenderer::DrawSpotLight(const Light &light) { SR_ASSERT(light.type == kLightSpotLight); }
void StackAllocator::FreeToMarker(Marker marker) { uchar *marker_ptr = reinterpret_cast<uchar*>(marker); SR_ASSERT(top_ >= marker_ptr); top_ = marker_ptr; }
void DeferredRenderer::SetCommonLightQuadDraw(Shader &shader) { Device *dev = Device::GetInstance(); RenderState &render_state = dev->render_state(); const mat4 &projection_mat = render_state.GetProjection3D(); const mat4 &view_mat = render_state.view_mat(); const mat4 &model_mat = render_state.model_mat(); mat4 modelview = view_mat * model_mat; //벡터방향만 잇으면 되니까 이동관련속성은 날리기 for(int i = 0 ; i < 3 ; ++i) { modelview[3][i] = 0; } vec4 viewport(0, 0, render_state.win_width(), render_state.win_height()); float pixels[4][2] = { { 0, 0 }, { viewport[2], 0 }, { viewport[2], viewport[3] }, { 0, viewport[3] }, }; vec3 view_vec_list[4]; for(int i = 0 ; i < 4 ; i++) { vec3 win_coord(pixels[i][0], pixels[i][1], 10); vec3 obj = glm::unProject(win_coord, modelview, projection_mat, viewport); vec3 &view_vec = view_vec_list[i]; view_vec = obj; vec3 cam_pos = MatrixHelper::ViewPos(view_mat); view_vec -= cam_pos; view_vec = glm::normalize(view_vec); mat3 modelview_mat3(modelview); view_vec = modelview_mat3 * view_vec; view_vec.z *= -1; //픽셀에서 cam_pos로 들어오는 방향으로 만들기 위해서 z뒤집음 } //fragment마다 view vector를 계산하기 위해서 계산에 필요한 정보까지 넣기 //4군데만 넣어주면 나머지는 알아서 적절히 보간될것이다 struct LightQuadVertex { LightQuadVertex(float x, float y, float s, float t, const vec3 &view_vec) : pos(x, y), texcoord(s, t), view_vec(view_vec) {} vec2 pos; vec2 texcoord; vec3 view_vec; }; vector<LightQuadVertex> vert_list; vert_list.push_back(LightQuadVertex(-1, -1, 0, 0, view_vec_list[0])); vert_list.push_back(LightQuadVertex(1, -1, 1, 0, view_vec_list[1])); vert_list.push_back(LightQuadVertex(1, 1, 1, 1, view_vec_list[2])); vert_list.push_back(LightQuadVertex(-1, 1, 0, 1, view_vec_list[3])); ShaderVariable pos_var = shader.attrib_var(kPositionHandleName); ShaderVariable texcoord_var = shader.attrib_var(kTexcoordHandleName); ShaderVariable view_vec_var = shader.attrib_var("a_viewVector"); { SR_ASSERT(pos_var.location != kInvalidShaderVarLocation); AttribBindParam param; param.dim = 2; param.normalize = false; param.offset = offsetof(LightQuadVertex, pos); param.var_type = GL_FLOAT; param.vert_size = sizeof(LightQuadVertex); void *ptr = &vert_list[0]; SetAttrib(pos_var, param, (char*)ptr); } { SR_ASSERT(texcoord_var.location != kInvalidShaderVarLocation); AttribBindParam param; param.dim = 2; param.normalize = false; param.offset = offsetof(LightQuadVertex, texcoord); param.var_type = GL_FLOAT; param.vert_size = sizeof(LightQuadVertex); void *ptr = &vert_list[0]; SetAttrib(texcoord_var, param, (char*)ptr); } if(view_vec_var.location != kInvalidShaderVarLocation) { AttribBindParam param; param.dim = 3; param.normalize = true; param.offset = offsetof(LightQuadVertex, view_vec); param.var_type = GL_FLOAT; param.vert_size = sizeof(LightQuadVertex); void *ptr = &vert_list[0]; SetAttrib(view_vec_var, param, (char*)ptr); } shader.DrawArrays(kDrawTriangleFan, vert_list.size()); /* vector<Vertex2D> vert_list; vert_list.push_back(CreateVertex2D(-1, -1, 0, 0)); vert_list.push_back(CreateVertex2D(1, -1, 1, 0)); vert_list.push_back(CreateVertex2D(1, 1, 1, 1)); vert_list.push_back(CreateVertex2D(-1, 1, 0, 1)); shader.DrawArrays(kDrawTriangleFan, vert_list); */ }
void DeferredRenderer::DrawPointLight(const Light &light) { SR_ASSERT(light.type == kLightPoint); Device *dev = Device::GetInstance(); RenderState &render_state = dev->render_state(); //해당위치의 스텐실 버퍼에 원을 그린다. 원으로 빛이 영향을 줄 영역을 결정해서 //depth test를 오래하지 않도록한다 //스텐실 버퍼에 의존하는 방식보다 scissor로 고치는게 성능상 유리할테니 //나중에는 적절히 고치자 //GeometricObject<vec3> sphere_mesh; //sphere_mesh.SolidSphere(1, 16, 16); //스텐실을 이용해서 그리면 화면 전체가 아니라 //빛이 영향을 받는 곳에 대해서만 구를 그려서 빛 계산을 하도록하니까 //계산부하를 줄일수잇다 const bool use_stencil = true; if(use_stencil) { //3d장면에 렌더링하기. 그래야 빛이 영향줄 구가 제대로 그려진다 render_state.Set3D(); const mat4 &projection = render_state.projection_mat(); const mat4 &view = render_state.view_mat(); mat4 model(1.0f); model = glm::translate(model, light.pos); model = glm::scale(model, vec3(light.radius)); mat4 mvp_3d = projection * view * model; //단색쉐이더로 대충 그리기. 스텐실 버퍼에만 그려지면 됨 //색칠 영역은 스텐실 버퍼니까 적절히 초기화하기 glEnable(GL_STENCIL_TEST); render_state.ClearBuffer(false, false, true, Color4ub::White()); glColorMask(false, false, false, false); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glStencilFunc(GL_ALWAYS, 0xff, 0xff); ShaderManager *shader_mgr = dev->shader_mgr(); Shader *const_color_shader = shader_mgr->Get(ShaderManager::kConstColor); render_state.UseShader(*const_color_shader); vec4 white(1.0f); const_color_shader->SetUniformVector(kConstColorHandleName, white); const_color_shader->SetUniformMatrix(kMVPHandleName, mvp_3d); //const DrawCmdData<vec3> &draw_cmd = sphere_mesh.cmd_list().at(0); //const_color_shader->SetVertexList(draw_cmd.vertex_list); //const_color_shader->DrawElements(draw_cmd.draw_mode, draw_cmd.index_list); const_color_shader->DrawMeshIgnoreMaterial(&GetSphereMesh()); } { //스텐실 영역에 잇는거 진짜로 그리기. 2D로 그리기 //이것을 진행하면서 빛 계산을 수행한다 if(use_stencil) { glColorMask(true, true, true, true); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 0xff, 0xff); } //점광원 계산용 쉐이더로 교체 Shader &point_shader = this->point_shader(); render_state.UseShader(point_shader); //빛 계산에 쓰이는 공용 속성 설정 SetCommonLightUniform(point_shader, light); const mat4 &view = render_state.view_mat(); const mat4 &model = render_state.model_mat(); vec4 light_pos = model * vec4(light.pos, 1.0f); light_pos.w = light.radius; //4번쨰를 반지름으로 사용 { //Draw2DManager *draw_2d_mgr = dev->draw_2d(); //char light_pos_buf[128]; //sprintf(light_pos_buf, "LightPos:%.4f, %.4f, %.4f", light_pos.x, light_pos.y, light_pos.z); //draw_2d_mgr->AddString(vec2(0, 100), light_pos_buf, Color4ub::Green(), 1.0f); //DebugDrawManager *draw_3d_mgr = dev->debug_draw_mgr(); //draw_3d_mgr->AddString(light.pos, "Light", Color4ub::Red(), 1.0f); } point_shader.SetUniformVector("u_lightPos", light_pos); //2d로 교체는 렌더링 직전에 수행하자 render_state.Set2D(); SetCommonLightQuadDraw(point_shader); } //restore state if(use_stencil) { glDisable(GL_STENCIL_TEST); } }
bool RPSEvent::operator==(const RPSEvent &o) const { SR_ASSERT(o.value != kNone); SR_ASSERT(this->value != kNone); return this->value == o.value; }