Reflection fresnel support, change API to require texture name instead of texture hash, support ray picking to edit texture mods.

This commit is contained in:
Dario 2021-04-14 20:31:14 -03:00
parent 470a1bb5e5
commit 44fbecce37
5 changed files with 122 additions and 26 deletions

View File

@ -24,19 +24,20 @@
#define RT64_MATERIAL_CC_SHADER_TEXEL1 7
// Material attributes.
#define RT64_ATTRIBUTE_NONE 0x0
#define RT64_ATTRIBUTE_IGNORE_NORMAL_FACTOR 0x1
#define RT64_ATTRIBUTE_NORMAL_MAP_SCALE 0x2
#define RT64_ATTRIBUTE_REFLECTION_FACTOR 0x4
#define RT64_ATTRIBUTE_REFLECTION_SHINE_FACTOR 0x8
#define RT64_ATTRIBUTE_REFRACTION_FACTOR 0x10
#define RT64_ATTRIBUTE_SPECULAR_INTENSITY 0x20
#define RT64_ATTRIBUTE_SPECULAR_EXPONENT 0x40
#define RT64_ATTRIBUTE_SOLID_ALPHA_MULTIPLIER 0x80
#define RT64_ATTRIBUTE_SHADOW_ALPHA_MULTIPLIER 0x100
#define RT64_ATTRIBUTE_SELF_LIGHT 0x200
#define RT64_ATTRIBUTE_LIGHT_GROUP_MASK_BITS 0x400
#define RT64_ATTRIBUTE_DIFFUSE_COLOR_MIX 0x800
#define RT64_ATTRIBUTE_NONE 0x0000
#define RT64_ATTRIBUTE_IGNORE_NORMAL_FACTOR 0x0001
#define RT64_ATTRIBUTE_NORMAL_MAP_SCALE 0x0002
#define RT64_ATTRIBUTE_REFLECTION_FACTOR 0x0004
#define RT64_ATTRIBUTE_REFLECTION_FRESNEL_FACTOR 0x0008
#define RT64_ATTRIBUTE_REFLECTION_SHINE_FACTOR 0x0010
#define RT64_ATTRIBUTE_REFRACTION_FACTOR 0x0020
#define RT64_ATTRIBUTE_SPECULAR_INTENSITY 0x0040
#define RT64_ATTRIBUTE_SPECULAR_EXPONENT 0x0080
#define RT64_ATTRIBUTE_SOLID_ALPHA_MULTIPLIER 0x0100
#define RT64_ATTRIBUTE_SHADOW_ALPHA_MULTIPLIER 0x0200
#define RT64_ATTRIBUTE_SELF_LIGHT 0x0400
#define RT64_ATTRIBUTE_LIGHT_GROUP_MASK_BITS 0x0800
#define RT64_ATTRIBUTE_DIFFUSE_COLOR_MIX 0x1000
// Mesh flags.
#define RT64_MESH_RAYTRACE_ENABLED 0x1
@ -83,6 +84,7 @@ typedef struct {
float ignoreNormalFactor;
float normalMapScale;
float reflectionFactor;
float reflectionFresnelFactor;
float reflectionShineFactor;
float refractionFactor;
float specularIntensity;
@ -95,7 +97,6 @@ typedef struct {
RT64_VECTOR4 diffuseColorMix;
float fogMul;
float fogOffset;
int _padA;
// N64 Color combiner parameters.
int c0[4];
@ -153,6 +154,10 @@ inline void RT64_ApplyMaterialAttributes(RT64_MATERIAL *dst, RT64_MATERIAL *src)
dst->reflectionFactor = src->reflectionFactor;
}
if (src->enabledAttributes & RT64_ATTRIBUTE_REFLECTION_FRESNEL_FACTOR) {
dst->reflectionFresnelFactor = src->reflectionFresnelFactor;
}
if (src->enabledAttributes & RT64_ATTRIBUTE_REFLECTION_SHINE_FACTOR) {
dst->reflectionShineFactor = src->reflectionShineFactor;
}
@ -196,6 +201,7 @@ typedef void(*DrawDevicePtr)(RT64_DEVICE* device, int vsyncInterval);
typedef void(*DestroyDevicePtr)(RT64_DEVICE* device);
typedef RT64_VIEW* (*CreateViewPtr)(RT64_SCENE* scenePtr);
typedef void(*SetViewPerspectivePtr)(RT64_VIEW* viewPtr, RT64_VECTOR3 eyePosition, RT64_VECTOR3 eyeFocus, RT64_VECTOR3 eyeUpDirection, float fovRadians, float nearDist, float farDist);
typedef RT64_INSTANCE* (*GetViewRaytracedInstanceAtPtr)(RT64_VIEW *viewPtr, int x, int y);
typedef void(*DestroyViewPtr)(RT64_VIEW* viewPtr);
typedef RT64_SCENE* (*CreateScenePtr)(RT64_DEVICE* devicePtr);
typedef void (*SetSceneLightsPtr)(RT64_SCENE* scenePtr, RT64_LIGHT* lightArray, int lightCount);
@ -210,7 +216,7 @@ typedef RT64_TEXTURE* (*CreateTextureFromRGBA8Ptr)(RT64_DEVICE* devicePtr, const
typedef void(*DestroyTexturePtr)(RT64_TEXTURE* texture);
typedef RT64_INSPECTOR* (*CreateInspectorPtr)(RT64_DEVICE* devicePtr);
typedef bool(*HandleMessageInspectorPtr)(RT64_INSPECTOR* inspectorPtr, UINT msg, WPARAM wParam, LPARAM lParam);
typedef void (*SetMaterialInspectorPtr)(RT64_INSPECTOR* inspectorPtr, RT64_MATERIAL* material);
typedef void (*SetMaterialInspectorPtr)(RT64_INSPECTOR* inspectorPtr, RT64_MATERIAL* material, const char *materialName);
typedef void(*SetLightsInspectorPtr)(RT64_INSPECTOR* inspectorPtr, RT64_LIGHT* lights, int *lightCount, int maxLightCount);
typedef void(*PrintToInspectorPtr)(RT64_INSPECTOR* inspectorPtr, const char* message);
typedef void(*DestroyInspectorPtr)(RT64_INSPECTOR* inspectorPtr);
@ -223,6 +229,7 @@ typedef struct {
DestroyDevicePtr DestroyDevice;
CreateViewPtr CreateView;
SetViewPerspectivePtr SetViewPerspective;
GetViewRaytracedInstanceAtPtr GetViewRaytracedInstanceAt;
DestroyViewPtr DestroyView;
CreateScenePtr CreateScene;
SetSceneLightsPtr SetSceneLights;
@ -258,6 +265,7 @@ inline RT64_LIBRARY RT64_LoadLibrary() {
lib.DestroyDevice = (DestroyDevicePtr)(GetProcAddress(lib.handle, "RT64_DestroyDevice"));
lib.CreateView = (CreateViewPtr)(GetProcAddress(lib.handle, "RT64_CreateView"));
lib.SetViewPerspective = (SetViewPerspectivePtr)(GetProcAddress(lib.handle, "RT64_SetViewPerspective"));
lib.GetViewRaytracedInstanceAt = (GetViewRaytracedInstanceAtPtr)(GetProcAddress(lib.handle, "RT64_GetViewRaytracedInstanceAt"));
lib.DestroyView = (DestroyViewPtr)(GetProcAddress(lib.handle, "RT64_DestroyView"));
lib.CreateScene = (CreateScenePtr)(GetProcAddress(lib.handle, "RT64_CreateScene"));
lib.SetSceneLights = (SetSceneLightsPtr)(GetProcAddress(lib.handle, "RT64_SetSceneLights"));

View File

@ -446,10 +446,14 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co
}
*node = &gfx_texture_cache.pool[gfx_texture_cache.pool_pos++];
if ((*node)->texture_addr == NULL) {
#ifndef GFX_REQUIRE_TEXTURE_HASH
(*node)->texture_id = gfx_rapi->new_texture();
#ifdef GFX_REQUIRE_TEXTURE_NAME
# ifdef EXTERNAL_DATA
(*node)->texture_id = gfx_rapi->new_texture((const char *)(orig_addr));
# else
# error "GFX_REQUIRE_TEXTURE_NAME requires EXTERNAL_DATA to be enabled."
# endif
#else
(*node)->texture_id = gfx_rapi->new_texture(string_hash(orig_addr));
(*node)->texture_id = gfx_rapi->new_texture();
#endif
}
gfx_rapi->select_texture(tile, (*node)->texture_id);

View File

@ -16,10 +16,10 @@ struct GfxRenderingAPI {
struct ShaderProgram *(*create_and_load_new_shader)(uint32_t shader_id);
struct ShaderProgram *(*lookup_shader)(uint32_t shader_id);
void (*shader_get_info)(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]);
#ifndef GFX_REQUIRE_TEXTURE_HASH
#ifndef GFX_REQUIRE_TEXTURE_NAME
uint32_t (*new_texture)(void);
#else
uint32_t (*new_texture)(uint64_t hash);
uint32_t (*new_texture)(const char *name);
#endif
void (*select_texture)(int tile, uint32_t texture_id);
void (*upload_texture)(const uint8_t *rgba32_buf, int width, int height);

View File

@ -10,7 +10,7 @@
# define GFX_OUTPUT_NORMALS_TO_VBO
# define GFX_SEPARATE_PROJECTIONS
# define GFX_SEPARATE_FOG
# define GFX_REQUIRE_TEXTURE_HASH
# define GFX_REQUIRE_TEXTURE_NAME
# define GFX_ENABLE_GRAPH_NODE_MODS
#endif

View File

@ -137,6 +137,12 @@ struct {
RT64_LIGHT levelLights[MAX_LEVELS][MAX_AREAS][MAX_LEVEL_LIGHTS];
int levelLightCounts[MAX_LEVELS][MAX_AREAS];
// Ray picking data.
bool pickTextureNextFrame;
bool pickTextureHighlight;
uint64_t pickedTextureHash;
std::unordered_map<RT64_INSTANCE *, uint64_t> lastInstanceTextureHashes;
// Geo layout mods.
void *geoLayoutStack[MAX_GEO_LAYOUT_STACK_SIZE];
int geoLayoutStackSize;
@ -410,6 +416,11 @@ void gfx_rt64_load_material_mod(const json &jmatmod, RT64_MATERIAL *materialMod)
materialMod->enabledAttributes |= RT64_ATTRIBUTE_REFLECTION_FACTOR;
}
if (jmatmod.find("reflectionFresnelFactor") != jmatmod.end()) {
materialMod->reflectionFresnelFactor = jmatmod["reflectionFresnelFactor"];
materialMod->enabledAttributes |= RT64_ATTRIBUTE_REFLECTION_FRESNEL_FACTOR;
}
if (jmatmod.find("reflectionShineFactor") != jmatmod.end()) {
materialMod->reflectionShineFactor = jmatmod["reflectionShineFactor"];
materialMod->enabledAttributes |= RT64_ATTRIBUTE_REFLECTION_SHINE_FACTOR;
@ -475,6 +486,10 @@ json gfx_rt64_save_material_mod(RT64_MATERIAL *materialMod) {
jmatmod["reflectionFactor"] = materialMod->reflectionFactor;
}
if (materialMod->enabledAttributes & RT64_ATTRIBUTE_REFLECTION_FRESNEL_FACTOR) {
jmatmod["reflectionFresnelFactor"] = materialMod->reflectionFresnelFactor;
}
if (materialMod->enabledAttributes & RT64_ATTRIBUTE_REFLECTION_SHINE_FACTOR) {
jmatmod["reflectionShineFactor"] = materialMod->reflectionShineFactor;
}
@ -737,6 +752,14 @@ LRESULT CALLBACK gfx_rt64_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARA
}
break;
case WM_RBUTTONDOWN:
RT64.pickedTextureHash = 0;
RT64.pickTextureNextFrame = true;
RT64.pickTextureHighlight = true;
break;
case WM_RBUTTONUP:
RT64.pickTextureHighlight = false;
break;
case WM_KEYDOWN:
if (wParam == VK_F5) {
gfx_rt64_save_geo_layout_mods();
@ -862,6 +885,9 @@ static void gfx_rt64_wapi_init(const char *window_title) {
RT64.fogColor.y = 0.0f;
RT64.fogColor.z = 0.0f;
RT64.fogMul = RT64.fogOffset = 0;
RT64.pickTextureNextFrame = false;
RT64.pickTextureHighlight = false;
RT64.pickedTextureHash = 0;
// Preload a blank texture.
int blankBytesCount = 256 * 256 * 4;
@ -884,6 +910,7 @@ static void gfx_rt64_wapi_init(const char *window_title) {
RT64.defaultMaterial.ignoreNormalFactor = 0.0f;
RT64.defaultMaterial.normalMapScale = 1.0f;
RT64.defaultMaterial.reflectionFactor = 0.0f;
RT64.defaultMaterial.reflectionFresnelFactor = 1.0f;
RT64.defaultMaterial.reflectionShineFactor = 0.0f;
RT64.defaultMaterial.refractionFactor = 0.0f;
RT64.defaultMaterial.specularIntensity = 1.0f;
@ -1089,15 +1116,15 @@ static void gfx_rt64_rapi_shader_get_info(struct ShaderProgram *prg, uint8_t *nu
used_textures[1] = prg->used_textures[1];
}
static uint32_t gfx_rt64_rapi_new_texture(uint64_t hash) {
static uint32_t gfx_rt64_rapi_new_texture(const char *name) {
uint32_t textureKey = RT64.textures.size();
auto &recordedTexture = RT64.textures[textureKey];
recordedTexture.texture = nullptr;
recordedTexture.linearFilter = 0;
recordedTexture.cms = 0;
recordedTexture.cmt = 0;
recordedTexture.hash = hash;
RT64.textureHashIdMap[hash] = textureKey;
recordedTexture.hash = gfx_rt64_get_texture_name_hash(name);
RT64.textureHashIdMap[recordedTexture.hash] = textureKey;
return textureKey;
}
@ -1361,8 +1388,12 @@ static void gfx_rt64_rapi_draw_triangles_common(RT64_MATRIX4 transform, float bu
RecordedMod *textureMod = nullptr;
bool linearFilter = false;
uint32_t cms = 0, cmt = 0;
// Create the instance.
RT64_INSTANCE *instance = gfx_rt64_rapi_add_instance();
// Find all parameters associated to the texture if it's used.
bool highlightMaterial = false;
if (RT64.shaderProgram->used_textures[0]) {
RecordedTexture &recordedTexture = RT64.textures[RT64.currentTextureIds[RT64.currentTile]];
linearFilter = recordedTexture.linearFilter;
@ -1377,6 +1408,13 @@ static void gfx_rt64_rapi_draw_triangles_common(RT64_MATRIX4 transform, float bu
if (texModIt != RT64.texMods.end()) {
textureMod = texModIt->second;
}
// Update data for ray picking.
if (RT64.pickTextureHighlight && (recordedTexture.hash == RT64.pickedTextureHash)) {
highlightMaterial = true;
}
RT64.lastInstanceTextureHashes[instance] = recordedTexture.hash;
}
// Build material with applied mods.
@ -1389,8 +1427,13 @@ static void gfx_rt64_rapi_draw_triangles_common(RT64_MATRIX4 transform, float bu
gfx_rt64_rapi_apply_mod(&material, &normalMapTexture, textureMod, transform);
}
// Create the instance and process the mesh that corresponds to the VBO.
RT64_INSTANCE *instance = gfx_rt64_rapi_add_instance();
if (highlightMaterial) {
material.diffuseColorMix = { 1.0f, 0.0f, 1.0f, 0.5f };
material.selfLight = { 1.0f, 1.0f, 1.0f };
material.lightGroupMaskBits = 0;
}
// Process the mesh that corresponds to the VBO.
RT64_MESH *mesh = gfx_rt64_rapi_process_mesh(buf_vbo, buf_vbo_len, buf_vbo_num_tris, raytrace);
// Mark the right instance flags.
@ -1496,6 +1539,47 @@ static void gfx_rt64_rapi_end_frame(void) {
sprintf(message, "RT64: %.3f ms\n", ElapsedMicroseconds.QuadPart / 1000.0);
RT64.lib.PrintToInspector(RT64.inspector, message);
// Left click allows to pick a texture for editing from the viewport.
if (RT64.pickTextureNextFrame) {
POINT cursorPos = {};
GetCursorPos(&cursorPos);
ScreenToClient(RT64.hwnd, &cursorPos);
RT64_INSTANCE *instance = RT64.lib.GetViewRaytracedInstanceAt(RT64.view, cursorPos.x, cursorPos.y);
if (instance != nullptr) {
auto instIt = RT64.lastInstanceTextureHashes.find(instance);
if (instIt != RT64.lastInstanceTextureHashes.end()) {
RT64.pickedTextureHash = instIt->second;
}
}
else {
RT64.pickedTextureHash = 0;
}
RT64.pickTextureNextFrame = false;
}
RT64.lastInstanceTextureHashes.clear();
// Edit last picked texture.
if (RT64.pickedTextureHash != 0) {
const std::string textureName = RT64.texNameMap[RT64.pickedTextureHash];
RecordedMod *texMod = RT64.texMods[RT64.pickedTextureHash];
if (texMod == nullptr) {
texMod = new RecordedMod();
texMod->materialMod = nullptr;
texMod->lightMod = nullptr;
texMod->normalMapHash = 0;
RT64.texMods[RT64.pickedTextureHash] = texMod;
}
if (texMod->materialMod == nullptr) {
texMod->materialMod = new RT64_MATERIAL();
texMod->materialMod->enabledAttributes = RT64_ATTRIBUTE_NONE;
}
RT64.lib.SetMaterialInspector(RT64.inspector, texMod->materialMod, textureName.c_str());
}
// Mesh key cleanup.
auto keyIt = RT64.dynamicMeshKeys.begin();
while (keyIt != RT64.dynamicMeshKeys.end()) {