I haven't done any investigation about Scaleform stuff until the July 7th 2023, but after playing around with Scaleform to replicate some of the orbital cannon map and the horse racing wall in the Diamond Casino, I realized researching render target stuff extends possibility in texture, text, and Scaleform movie drawing. Why don't we play around with render target and gather info about it so we can design well-designed APIs for render target? Here's what I know about render target: How to Use Render TargetRender targets only works for models that have textures with name starting withscript_rt_ (hardcoded in the exe, capital doesn't matter), such asscript_rt_orbital_table. First, you need to register a register target for a model. You register one like this way: // you can't define your custom names that don't follow the `script_rt_` rule!if(!Function.Call<bool>(Hash.IS_NAMED_RENDERTARGET_REGISTERED,"orbital_table")){Function.Call(Hash.REGISTER_NAMED_RENDERTARGET,"orbital_table",false);inttableModelHash=Game.GenerateHash("xm_prop_orbital_cannon_table");// a render target may be registered for the model, so test thisif(!Function.Call<bool>(Hash.IS_NAMED_RENDERTARGET_LINKED,tableModelHash)){Function.Call(Hash.LINK_NAMED_RENDERTARGET,tableModelHash);renderTargetId=Function.Call<int>(Hash.GET_NAMED_RENDERTARGET_RENDER_ID,"orbital_table");}}Then, you draw on the texture for the register target like this: Function.Call(Hash.SET_TEXT_RENDER_ID,renderTargetId);Function.Call(Hash.SET_SCRIPT_GFX_DRAW_ORDER,4);// only 4 (GFX_ORDER_AFTER_HUD) worksFunction.Call(Hash.SET_SCRIPT_GFX_DRAW_BEHIND_PAUSEMENU,true);Function.Call(Hash.DRAW_SCALEFORM_MOVIE,scaleformId,0.445f,0.501f,0.886f,0.997f,255,255,255,255,0);// Scaleform.Render2DScreenSpace is too inconvenient to draw scaleform movie on a texture for the orbital cannon map// if you want to draw texts, you can.../* * var textElem = new TextElement("scaleformId: " + scaleformId.ToString(), new Point(0, 480), 0.5f, Color.White, * GTA.UI.Font.ChaletLondon, Alignment.Left, true, false); */Function.Call(Hash.SET_TEXT_RENDER_ID,Function.Call<int>(Hash.GET_DEFAULT_SCRIPT_RENDERTARGET_RENDER_ID));// you want to revert the current render target to the default oneThe allocated texture for the render target applies to all props with the same render target material/texture. When you want to release your render targets, like this: if(Function.Call<bool>(Hash.IS_NAMED_RENDERTARGET_REGISTERED,"orbital_table")){Function.Call(Hash.RELEASE_NAMED_RENDERTARGET,"orbital_table");}What happens when different prop models have the same the render target?Well, if you try to register render targets for different prop models but has a shared render target name, something you probably don't want happen.  The left TV usesdes_tvsmash_root, and the right one usesdes_tvsmash_start btw.
You can't create separate render targets for different prop models with the same render target name. If you want separate textures for render targets when you create model assets, use different names. Render Target PoolThere's a pool that holds structs of render targets currently used. Each item takes 0x40 bytes, and the layout is like this: // I don't know the exact struct name or member names, sorrytypedefstructItemForRenderTargetInfoPool{int32_t pad;uint32_t scrThread_index;// probablyuint32_t render_target_id;// confirmeduint16_t model_index;// confirmed, not model index. if 0xFFFF, then assume the value invalid.uint16_t pad2;int32_t pad3;int32_t pad4; rage::grcTexture *texture;// you'll see a rage::grcTextureDX11 instance unless you run the game with DX10 rage::grcRenderTarget *render_target;// you'll see a rage::grcRenderTargetDX11 instance unless you run the game with DX10int32_t pad5_array[6];} ItemForRenderTargetInfoPool;You can find a function for said pool with44 8B C7 49 8B CD 8B D0 E8 ? ? ? ? 84 C0 75 16. The max value of items can vary in different game versions (b372: 16, b2699 and b2944: 48). |