void csm_renderpreview(gfx_cmdqueue cmdqueue, const struct gfx_view_params* params) { struct gfx_shader* shader = gfx_shader_get(g_csm->prev_shader); gfx_output_setrendertarget(cmdqueue, g_csm->prev_rt); gfx_output_setviewport(cmdqueue, 0, 0, CSM_PREV_SIZE, CSM_PREV_SIZE); gfx_shader_bind(cmdqueue, shader); /* constants */ struct vec4f orthoparams[CSM_CASCADE_CNT]; float max_fars[CSM_CASCADE_CNT]; for (uint i = 0; i < CSM_CASCADE_CNT; i++) { const struct mat4f* ortho = &g_csm->cascades[i].proj; vec4_setf(&orthoparams[i], ortho->m11, ortho->m22, ortho->m33, ortho->m43); max_fars[i] = g_csm->cascades[i].nfar; } gfx_shader_set4fv(shader, SHADER_NAME(c_orthoparams), orthoparams, CSM_CASCADE_CNT); gfx_shader_setfv(shader, SHADER_NAME(c_max_far), max_fars, CSM_CASCADE_CNT); gfx_shader_bindconstants(cmdqueue, shader); /* textures */ gfx_shader_bindsamplertexture(cmdqueue, shader, SHADER_NAME(s_shadowmap), g_csm->sampl_linear, g_csm->shadow_tex); /* draw */ gfx_draw_fullscreenquad(); gfx_set_previewrenderflag(); }
void gfx_csm_render(gfx_cmdqueue cmdqueue, gfx_rendertarget rt, const struct gfx_view_params* params, struct gfx_batch_item* batch_items, uint batch_cnt, void* userdata, OUT struct gfx_rpath_result* result) { ASSERT(batch_cnt != 0); PRF_OPENSAMPLE("rpath-csm"); int supports_shared_cbuff = gfx_check_feature(GFX_FEATURE_RANGED_CBUFFERS); if (supports_shared_cbuff) csm_submit_batchdata(cmdqueue, batch_items, batch_cnt, g_csm->sharedbuff); gfx_cmdqueue_resetsrvs(cmdqueue); gfx_output_setrendertarget(cmdqueue, g_csm->shadow_rt); gfx_output_setviewport(cmdqueue, 0, 0, CSM_SHADOW_SIZE, CSM_SHADOW_SIZE); gfx_output_setrasterstate(cmdqueue, g_csm->rs_bias); gfx_output_setdepthstencilstate(cmdqueue, g_csm->ds_depth, 0); gfx_output_clearrendertarget(cmdqueue, g_csm->shadow_rt, NULL, 1.0f, 0, GFX_CLEAR_DEPTH); struct gfx_cblock* cb_frame = g_csm->cb_frame; struct gfx_cblock* cb_frame_gs = g_csm->cb_frame_gs; struct mat3f* views[CSM_CASCADE_CNT]; float fovfactors[4]; float texelsz[4] = {1.0f / (float)CSM_SHADOW_SIZE, 0, 0, 0}; for (uint i = 0; i < CSM_CASCADE_CNT && i < 4; i++) { views[i] = &g_csm->cascades[i].view; fovfactors[i] = maxf(g_csm->cascades[i].proj.m11, g_csm->cascades[i].proj.m22); } gfx_cb_set4f(cb_frame, SHADER_NAME(c_texelsz), texelsz); gfx_cb_set4f(cb_frame, SHADER_NAME(c_fovfactors), fovfactors); gfx_cb_set4f(cb_frame, SHADER_NAME(c_lightdir), g_csm->light_dir.f); gfx_cb_set3mvp(cb_frame, SHADER_NAME(c_views), (const struct mat3f**)views, CSM_CASCADE_CNT); gfx_cb_set4mv(cb_frame, SHADER_NAME(c_cascade_mats), g_csm->cascade_vps, CSM_CASCADE_CNT); gfx_shader_updatecblock(cmdqueue, cb_frame); gfx_cb_set4fv(cb_frame_gs, SHADER_NAME(c_cascade_planes), g_csm->cascade_planes, 4*CSM_CASCADE_CNT); gfx_shader_updatecblock(cmdqueue, cb_frame_gs); for (uint i = 0; i < batch_cnt; i++) { struct gfx_batch_item* bitem = &batch_items[i]; struct gfx_shader* shader = gfx_shader_get(bitem->shader_id); ASSERT(shader); gfx_shader_bind(cmdqueue, shader); /* do not send cb_xforms to shader if we are using shared buffer (bind later before draw) */ struct gfx_cblock* cbs[3]; uint xforms_shared_idx; if (supports_shared_cbuff) { cbs[0] = cb_frame; cbs[1] = cb_frame_gs; xforms_shared_idx = 2; } else { cbs[0] = cb_frame; cbs[1] = cb_frame_gs; cbs[2] = g_csm->cb_xforms; xforms_shared_idx = 3; } gfx_shader_bindcblocks(cmdqueue, shader, (const struct gfx_cblock**)cbs, xforms_shared_idx); /* batch draw */ for (int k = 0; k < bitem->nodes.item_cnt; k++) { struct gfx_batch_node* bnode_first = &((struct gfx_batch_node*)bitem->nodes.buffer)[k]; csm_preparebatchnode(cmdqueue, bnode_first, shader); if (bnode_first->poses[0] != NULL) { gfx_shader_bindcblock_tbuffer(cmdqueue, shader, SHADER_NAME(tb_skins), g_csm->tb_skins); } struct linked_list* node = bnode_first->bll; while (node != NULL) { struct gfx_batch_node* bnode = (struct gfx_batch_node*)node->data; csm_drawbatchnode(cmdqueue, bnode, shader, xforms_shared_idx); node = node->next; } } } /* switch back */ gfx_output_setrasterstate(cmdqueue, NULL); gfx_output_setdepthstencilstate(cmdqueue, NULL, 0); if (g_csm->debug_csm) csm_renderpreview(cmdqueue, params); PRF_CLOSESAMPLE(); /* csm */ }
GfxSkyMaterial::GfxSkyMaterial (const std::string &name) : GfxBaseMaterial(name, gfx_shader_get("/system/SkyDefault")), sceneBlend(GFX_SKY_MATERIAL_OPAQUE) { }
result_t gfx_csm_init(uint width, uint height) { result_t r; log_printf(LOG_INFO, "init csm render-path ..."); struct allocator* lsr_alloc = eng_get_lsralloc(); struct allocator* tmp_alloc = tsk_get_tmpalloc(0); g_csm = (struct gfx_csm*)ALIGNED_ALLOC(sizeof(struct gfx_csm), MID_GFX); if (g_csm == NULL) return RET_OUTOFMEMORY; memset(g_csm, 0x00, sizeof(struct gfx_csm)); /* render targets and buffers */ r = csm_create_shadowrt(CSM_SHADOW_SIZE, CSM_SHADOW_SIZE); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "gfx-csm init failed: could not create shadow map buffers"); return RET_FAIL; } if (BIT_CHECK(eng_get_params()->flags, ENG_FLAG_DEV)) { if (!csm_load_prev_shaders(lsr_alloc)) { err_print(__FILE__, __LINE__, "gfx-csm init failed: could not load preview shaders"); return RET_FAIL; } r = csm_create_prevrt(CSM_PREV_SIZE, CSM_PREV_SIZE); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "gfx-csm init failed: could not create prev buffers"); return RET_FAIL; } /* console commands */ con_register_cmd("gfx_debugcsm", csm_console_debugcsm, NULL, "gfx_debugcsm [1*/0]"); } /* shaders */ if (!csm_load_shaders(lsr_alloc)) { err_print(__FILE__, __LINE__, "gfx-csm init failed: could not load shaders"); return RET_FAIL; } /* cblocks */ if (gfx_check_feature(GFX_FEATURE_RANGED_CBUFFERS)) { g_csm->sharedbuff = gfx_sharedbuffer_create(GFX_DEFAULT_RENDER_OBJ_CNT*GFX_INSTANCES_MAX*48); if (g_csm->sharedbuff == NULL) { err_print(__FILE__, __LINE__, "gfx-deferred init failed: could not create uniform buffer"); return RET_FAIL; } } g_csm->cb_frame = gfx_shader_create_cblock(lsr_alloc, tmp_alloc, gfx_shader_get(g_csm->shaders[0].shader_id), "cb_frame", NULL); g_csm->cb_xforms = gfx_shader_create_cblock(lsr_alloc, tmp_alloc, gfx_shader_get(g_csm->shaders[0].shader_id), "cb_xforms", g_csm->sharedbuff); g_csm->cb_frame_gs = gfx_shader_create_cblock(lsr_alloc, tmp_alloc, gfx_shader_get(g_csm->shaders[0].shader_id), "cb_frame_gs", NULL); g_csm->tb_skins = gfx_shader_create_cblock_tbuffer(mem_heap(), gfx_shader_get(gfx_csm_getshader(CMP_OBJTYPE_MODEL, GFX_RPATH_SKINNED | GFX_RPATH_CSMSHADOW)), "tb_skins", sizeof(struct vec4f)*3*GFX_INSTANCES_MAX*GFX_SKIN_BONES_MAX); if (g_csm->cb_frame == NULL || g_csm->cb_xforms == NULL || g_csm->cb_frame_gs == NULL || g_csm->tb_skins == NULL) { err_print(__FILE__, __LINE__, "gfx-csm init failed: could not create cblocks"); return RET_FAIL; } /* states */ r = csm_create_states(); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "gfx-csm init failed: could not create states"); return RET_FAIL; } g_csm->shadowmap_size = (float)CSM_SHADOW_SIZE; return RET_OK; }
struct gfx_model_mtlgpu* model_load_gpumtl(struct allocator* main_alloc, struct allocator* alloc, struct allocator* tmp_alloc, const struct gfx_model_mtl* mtl, uint rpath_flags) { struct gfx_model_mtlgpu* gmtl = (struct gfx_model_mtlgpu*)A_ALLOC(alloc, sizeof(struct gfx_model_mtlgpu), MID_GFX); ASSERT(gmtl); memset(gmtl, 0x00, sizeof(struct gfx_model_mtlgpu)); for (uint i = 0; i < GFX_MODEL_MAX_MAPS; i++) gmtl->textures[i] = INVALID_HANDLE; /* load textures */ for (uint i = 0; i < mtl->map_cnt; i++) { enum gfx_model_maptype type = mtl->maps[i].type; int srgb = FALSE; if (type == GFX_MODEL_DIFFUSEMAP || type == GFX_MODEL_REFLECTIONMAP || type == GFX_MODEL_EMISSIVEMAP) { srgb = TRUE; } gmtl->textures[type] = rs_load_texture(mtl->maps[i].filepath, 0, srgb, 0); if (gmtl->textures[type] == INVALID_HANDLE) { model_destroy_gpumtl(alloc, gmtl); return NULL; } } const struct gfx_rpath* rpath; /* render-passes for each material */ /* PRIMARY pass */ rpath = gfx_rpath_detect(CMP_OBJTYPE_MODEL, rpath_flags); gmtl->passes[GFX_RENDERPASS_PRIMARY].rpath = rpath; if (rpath != NULL) { gmtl->passes[GFX_RENDERPASS_PRIMARY].shader_id = rpath->getshader_fn(CMP_OBJTYPE_MODEL, rpath_flags); if (gmtl->passes[GFX_RENDERPASS_PRIMARY].shader_id == 0) { log_printf(LOG_WARNING, "unsupported shader for render-path '%s' : %s", rpath->name, gfx_rpath_getflagstr(rpath_flags)); model_destroy_gpumtl(alloc, gmtl); return NULL; } } /* sun shadow pass */ rpath = gfx_rpath_detect(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_CSMSHADOW); gmtl->passes[GFX_RENDERPASS_SUNSHADOW].rpath = rpath; if (rpath != NULL) { gmtl->passes[GFX_RENDERPASS_SUNSHADOW].shader_id = rpath->getshader_fn(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_CSMSHADOW); } /* spot shadow pass */ rpath = gfx_rpath_detect(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_SPOTSHADOW); gmtl->passes[GFX_RENDERPASS_SPOTSHADOW].rpath = rpath; if (rpath != NULL) { gmtl->passes[GFX_RENDERPASS_SPOTSHADOW].shader_id = rpath->getshader_fn(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_SPOTSHADOW); } /* point shadow pass */ rpath = gfx_rpath_detect(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_POINTSHADOW); gmtl->passes[GFX_RENDERPASS_POINTSHADOW].rpath = rpath; if (rpath != NULL) { gmtl->passes[GFX_RENDERPASS_POINTSHADOW].shader_id = rpath->getshader_fn(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_POINTSHADOW); } /* mirror/reflection pass */ rpath = gfx_rpath_detect(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_MIRROR); gmtl->passes[GFX_RENDERPASS_MIRROR].rpath = rpath; if (rpath != NULL) { gmtl->passes[GFX_RENDERPASS_MIRROR].shader_id = rpath->getshader_fn(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_MIRROR); } /* transparent pass */ rpath = gfx_rpath_detect(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_ALPHABLEND); gmtl->passes[GFX_RENDERPASS_TRANSPARENT].rpath = rpath; if (rpath != NULL) { gmtl->passes[GFX_RENDERPASS_TRANSPARENT].shader_id = rpath->getshader_fn(CMP_OBJTYPE_MODEL, rpath_flags | GFX_RPATH_ALPHABLEND); } /* cblock for material: use primary shader for it's creation */ /* note that cblock of mtl can be NULL, because some render-paths like deferred may not use it*/ gmtl->cb = gfx_shader_create_cblock(main_alloc, tmp_alloc, gfx_shader_get(gmtl->passes[GFX_RENDERPASS_PRIMARY].shader_id), "cb_mtl", NULL); /* if could not find 'cb_mtl' in the shader, try creating it in raw mode (w/o gpu_buffer) */ if (gmtl->cb == NULL) { static const struct gfx_constant_desc constants[] = { {"c_mtl_ambientclr", 0, GFX_CONSTANT_FLOAT4, 16, 1, 16, 0}, {"c_mtl_diffuseclr", 0, GFX_CONSTANT_FLOAT4, 16, 1, 16, 16}, {"c_mtl_specularclr", 0, GFX_CONSTANT_FLOAT4, 16, 1, 16, 32}, {"c_mtl_emissiveclr", 0, GFX_CONSTANT_FLOAT4, 16, 1, 16, 48}, {"c_mtl_props", 0, GFX_CONSTANT_FLOAT4, 16, 1, 16, 64} }; gmtl->cb = gfx_shader_create_cblockraw(main_alloc, "cb_mtl", constants, 5); } return gmtl; }