Announcement

Collapse
No announcement yet.

Assign Texture to model

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Assign Texture to model

    After getting back to the 2D canvas basics, I fiddled with the Chart3D sample. I was able to alter the chartmeshes, add new stuff like a simple cube, manipulate the light source and kinda understand how the holographic canvas property works. So far so good.

    Now I would like to put a texture onto a mesh for example. a simple cube or plane. Went through the helpfile and saw Tmodeltexture and TScenetexture. Since the Scenetexture has a "beginscene" and a "endscene" Im guessing that you somehow have to specify a target mesh surface and then actually render a texture on it?

    Also, is it currently possible to make the model viewer also load MTL files with an OBJ file?

  • #2
    I have attached Cube and CubeTextured examples for Lazarus, mostly ported from the similar example from C++: CubeExamples.zip
    Click image for larger version  Name:	CubeTextured.png Views:	0 Size:	156.2 KB ID:	48

    In order to add texturing to an existing scene, you need to add "SceneTexture" flag to "Attributes" parameter in "ModelSceneInit":
    Code:
      FSceneModel := ModelSceneInit(FDevice, TShadowTechnique.None, SceneLighting or SceneTexture, VertexElements);
    You also need to declare texture coordinates in vertex declaration, for example:
    Code:
    const
      VertexElements: array[0..2] of TVertexElement = (
        (Name: 'streamPosition'; Format: TElementFormat.Float; Count: 3; Channel: 0; Offset: 0),
        (Name: 'streamNormal'; Format: TElementFormat.Float; Count: 3; Channel: 0; Offset: 0),
        (Name: 'streamTexCoord'; Format: TElementFormat.Float; Count: 2; Channel: 0; Offset: 0));
    You will need to create TSampler and configure its sampler state to be used with the scene:
    Code:
      LSamplerState := TSamplerState.Default;
      LSamplerState.FilterMin := TTextureFilter.Linear;
      LSamplerState.FilterMag := TTextureFilter.Linear;
      LSamplerState.FilterMip := TTextureFilter.Linear;
      LSamplerState.Address[0] := TTextureAddress.Wrap;
      LSamplerState.Address[1] := TTextureAddress.Wrap;
    
      FSampler := SamplerInit(FDevice, LSamplerState);
    Finally, when rendering, you'll need to assign texture to model scene and bind the sampler:
    Code:
        FSceneModel.Texture[TSceneTextureType.Model] := FTexture; // Assign texture to the model.
    
        if FSceneModel.BeginScene then
        try
          FSampler.Bind; // Bind texture sampler.
    
          FSceneModel.World := TMatrix4f.RotateY(Pi * 0.5);
          FModelCube.Draw(FSceneModel.SceneProgram);
        finally
          FSampler.Unbind; // Remember to unbind the sampler.
          FSceneModel.EndScene;
        end;
    Please note that if you want to mix textured and non-textured objects, you'll have to create two separate scenes, one with "SceneTextured" attribute and another without. You'll be rendering with both like the following:
    Code:
        FSceneModelTextured.Texture[TSceneTextureType.Model] := FTexture;
        if FSceneModelTextured.BeginScene then
        try
          FSampler.Bind;
          FSceneModel.World := TMatrix4f.RotateY(Pi * 0.5);
          FModelCube.Draw(FSceneModelTextured.SceneProgram);
        finally
          FSampler.Unbind;
          FSceneModelTextured.EndScene;
        end;
        if FSceneModel.BeginScene then
        try
          FSceneModel.World := TMatrix4f.Translate(0.0, 0.0, 100.0);
          FModelCube.Draw(FSceneModel.SceneProgram);
        finally
          FSceneModel.EndScene;
        end;
    TModelTexture object that you mentioned is used for a different purpose - it is basically a container with color and depth textures. This is useful for rendering 3D scene for some post-processing. It is also a particularly useful when creating application for Linux with Wayland, where no multisampling is supported for the main application. In this case, you create TModelTexture with multisampling, render the scene to it, then simply call TModelTexture.Present to render the final contents in the application.

    Regarding the last question: MTL files are loaded automatically with OBJ files, but only material color is taken into account (as vertex color, which also must be present in vertex declaration, as in ModelViewer example). For texture, you'll have to apply it using aforementioned technique.

    Comment


    • #3
      Once again Big Kudos for your effort creating additional examples!

      Comment


      • #4
        Was able to play around with the 3D models, added another texture, learned a bit about repositioning objects and how it works and I was able to add a second lightsource after I found the correct parameter for the Tmodelscene init. Very exciting to understand more and more of it.

        Is it currently possible to limit the range of a light source?
        Easily capture screenshots, GIFs, and replays that are ready to share. Download the free app for windows and mac.

        Comment


        • #5
          In current version of Afterwarp v1, all light sources are considered point lights with an infinite range, so lighting is only limited by shadows. However, as in incoming Afterwarp v2 there is light attenuation, I believe it is fairly easy to back-port this to Afterwarp v1, as it is a trivial change. It'll be included in Afterwarp v1.06 update coming soon.

          Comment


          • #6
            Sounds great

            Just one more thing I need to figure out now then I stop nagging you for a while. I want to create a mixed 2D/3D adventure engine this time and thought about using planes for all the 2D elements instead of using the canvas. Like modern windows ports of Doom ect handle all the sprites.

            I got textured planes working but the alpha channel seems to be ignored (so it's a solid rectange image with no transparent areas) The same texture is rendered correctly on a canvas but not on a 3D model like a plane.

            I hope this is just a matter of setting the correct flags.

            Comment


            • #7
              If you want to render textured model with transparency, you need to enable alpha-blending. You can do so by adjusting rendering state after FSceneModel.BeginScene call and before any rendering calls:
              Code:
              var
                LRenderingState: TRenderingState;
              begin
                // FSceneModel.BeginScene was called
              
                // Read current rendering state.
                LRenderingState := FDevice.RenderingState;
              
                // Disable back-face culling, if model is double-sided.
                LRenderingState.CullFace := TTriangleFace.None;
              
                // Enable alpha-blending state.
                LRenderingState.States := LRenderingState.States or StateBlendEnable;
              
                // Configure blending mode.
                LRenderingState.BlendColor.Source := TBlendFactor.SourceAlpha;
                LRenderingState.BlendColor.Dest := TBlendFactor.InvSourceAlpha;
                LRenderingState.BlendColor.Op := TBlendOp.Add;
                LRenderingState.BlendAlpha.Source := TBlendFactor.One;
                LRenderingState.BlendAlpha.Dest := TBlendFactor.One;
                LRenderingState.BlendAlpha.Op := TBlendOp.Add;
              
                // Update rendering state.
                FDevice.RenderingState := LRenderingState;
              
                // Now issue draw calls...
              end;
              Please note that if texture has semi-transparent areas (instead of holdes with sharp edges), then when rendering multiple semi-transparent textures overlapped this way, you may encounter transparency artifacts, because alpha-blending is order dependent: this means that semi-transparent objects always need to be rendered in a sorted order from back to front. An easy solution, if you have multi-sampling enabled, is to add "StateAlphaToCoverage" state, e.g.:
              Code:
                // Enable alpha-blending state.
                LRenderingState.States := LRenderingState.States or StateBlendEnable or StateAlphaToCoverage;
              This would convert alpha values into the appropriate multi-sampling patterns, but the precision will be limited by the number of samples (8 for Direct3D, 32 for OpenGL on some recent Nvidia graphics cards).

              Another solution is to use Order-Independent Transparency, which is supported by the framework, but it requires few more housekeeping tasks - you need to render both solid and semi-transparent scenes separately to textures, then compose them together. This technique is shown both in ModelView and CubePlayground examples.

              Comment


              • #8
                Works perfectly. Thanks once again.
                Easily capture screenshots, GIFs, and replays that are ready to share. Download the free app for windows and mac.
                Last edited by Zimond; 12-27-2019, 04:08 PM.

                Comment


                • #9
                  Easily capture screenshots, GIFs, and replays that are ready to share. Download the free app for windows and mac.

                  Comment

                  Working...
                  X