ogre-next吃鸡笔记

本人使用的版本是ogre-next2.3

一、OgreSTBICodec.cpp 中decode()函数  解码24位图片有bug,会导致jpg或者24位png无法显示

修复如下:

  Codec::DecodeResult STBIImageCodec::decode(DataStreamPtr& input) const
    {
        // Buffer stream into memory (TODO: override IO functions instead?)
        MemoryDataStream memStream(input, true);

        int width, height, components;
        stbi_uc *pixelData = stbi_load_from_memory(
            memStream.getPtr(), static_cast( memStream.size() ), &width, &height, &components, 0 );

        if (!pixelData)
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
                "Error decoding image: " + String(stbi_failure_reason()),
                "STBIImageCodec::decode");
        }

        ImageData2* imgData = OGRE_NEW ImageData2();

        imgData->box.depth = 1u; // only 2D formats handled by this codec
        imgData->box.numSlices = 1u;
        imgData->box.width = static_cast( width );
        imgData->box.height = static_cast( height );
        imgData->numMipmaps = 1u; // no mipmaps in non-DDS
        imgData->textureType = TextureTypes::Type2D;

        switch( components )
        {
            case 1:
                imgData->format = PFG_R8_UNORM;
                break;
            case 2:
                imgData->format = PFG_RG8_UNORM;
                break;
            case 3:
                imgData->format = PFG_RGBA8_UNORM;
                break;
            case 4:
                imgData->format = PFG_RGBA8_UNORM;
                break;
            default:
                stbi_image_free(pixelData);
                OGRE_DELETE imgData;
                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
                            "Unknown or unsupported image format",
                            "STBIImageCodec::decode");
                break;
        }

        const uint32 rowAlignment = 4u;
        imgData->box.bytesPerPixel = PixelFormatGpuUtils::getBytesPerPixel( imgData->format );
        imgData->box.bytesPerRow = PixelFormatGpuUtils::getSizeBytes( imgData->box.width,
                                                                      1u, 1u, 1u,
                                                                      imgData->format,
                                                                      rowAlignment );
        imgData->box.bytesPerImage = imgData->box.bytesPerRow * imgData->box.height;

        imgData->box.data = OGRE_MALLOC_SIMD( imgData->box.bytesPerImage, MEMCATEGORY_RESOURCE );

        if( components != 3 )
            memcpy( imgData->box.data, pixelData, imgData->box.bytesPerImage );
        else
        {
            size_t realBytesPerRow = PixelFormatGpuUtils::getSizeBytes( imgData->box.width, 1u, 1u, 1u,
                                                                        PFG_RGB8_UNORM, rowAlignment );
            for( size_t y = 0; y < (size_t)height; ++y )
            {
                uint8 *pDst = reinterpret_cast( imgData->box.at( 0u, y, 0u ) );
                uint8 const *pSrc = pixelData + y * realBytesPerRow;
                for( size_t x = 0; x < (size_t)width; ++x )
                {
                    const uint8 b = *pSrc++;
                    const uint8 g = *pSrc++;
                    const uint8 r = *pSrc++;

                    *pDst++ = b;
                    *pDst++ = g;
                    *pDst++ = r;
                    *pDst++ = 0xFF;
                }
            }
        }
        stbi_image_free(pixelData);

        DecodeResult ret;
        ret.first.reset();
        ret.second = CodecDataPtr(imgData);
        return ret;
    }

二、PBR材质使用

    一个简单的材质如下

hlms FireHydrant_01_Green_FireHydrant_01_Green pbs
{
    roughness    0.38
    fresnel        1.33
    specular    1.0 1.0 1.0
    
    diffuse        3.14 3.14 3.14
    emissive 0.05 0.05 0.05
    workflow metallic_workflow
    diffuse_map        FireHydrant_01_Green_C.png
    normal_map        FireHydrant_01_N.png
    //roughness_map    FireHydrant_01_R.png
    specular_map    FireHydrant_01_M.png

}

注意Ogre支持三种PBR的工作流定义在OgreHlmsPbsDatablock.h文件中。默认的工作流是

SpecularWorkflow这个和国内常用的MetallicWorkflow不一致。

 enum Workflows
        {
            /// Specular workflow. Many popular PBRs use SpecularAsFresnelWorkflow
            /// though. @see setWorkflow
            SpecularWorkflow,

            /// Specular workflow where the specular texture is addressed to the fresnel
            /// instead of kS. This is normally referred as simply Specular workflow
            /// in many other PBRs. @see setWorkflow
            SpecularAsFresnelWorkflow,

             Metallic workflow. @see setWorkflow
            MetallicWorkflow,
        };

修改了OgreHlmsPbsDatablock.cpp文件中HlmsPbsDatablock的构造函数,增加Pbr材质中

workflow 关键字的支持,以通过材质指定工作流。增加代码如下:

 if( Hlms::findParamInVec( params, "uv_detail_weight_map", paramVal ) )
        {
            setTextureUvSource( PBSM_DETAIL_WEIGHT,
                                StringConverter::parseUnsignedInt( paramVal ) );
        }

        if( Hlms::findParamInVec( params, "workflow", paramVal ) )
        {
            if(paramVal.compare("metallic_workflow") == 0 )
            {
                setWorkflow( MetallicWorkflow );
            }
            else if (paramVal.compare("fresnel_workflow") == 0 )
            {
                setWorkflow( SpecularAsFresnelWorkflow );
            }
            else
            {
                setWorkflow( SpecularWorkflow );
            }  
        }

另外如果我们想知道pbr材质中支持哪些参数也可以查看该函数。比如:

  “background_diffuse”  “diffuse” “specular” “diffuse_map” 等等

      

三、调试Pbs生成的shader. HLMS材质系统通过各种预定义的语法片段来生成最终shader.

例如在prb材质中设置好

        specular_map    FireHydrant_01_M.png

则会用到    “Hlms/Pbs/Any/Main/800.PixelShader_piece_ps.any” 这个文件中的片段来生成对specular_map    采样的shader。我们可以通过修改这个文件来调试这部分代码例如修改该文件

如下。增加一个中间变量 fff 合 ddd 可以看到在最中的shader中会存在该部分。在debug模式下

ogrenext会默认将shader保存成文件。ogre保存该调试shader代码的函数在 OgreHlms.cpp文件中的 void Hlms::compileShaderCode( ShaderCodeCache &codeCache )函数中的

         if( mDebugOutput )
                    debugDumpFile.write( &outString[0], outString.size() );

        

@piece( SampleSpecularMap )
	/// SPECUlAR MAP
	pixelData.specular.xyz = material.kS.xyz;
	@property( !metallic_workflow )
		pixelData.F0 = material.F0.@insertpiece( FresnelSwizzle );
		@property( specular_map && !fresnel_workflow )
		float3 fff =  SampleSpecular( textureMaps@value( specular_map_idx ),
													  samplerState@value(specular_map_sampler),
													  UV_SPECULAR( inPs.uv@value(uv_specular).xy ),
													  texIndex_specularIdx ).xyz;
			fff.g = fff.r;
			fff.b = fff.r;
			pixelData.specular.xyz *= fff;
		@end
		@property( specular_map && fresnel_workflow )
			pixelData.F0 *= SampleSpecular( textureMaps@value( specular_map_idx ),
											samplerState@value(specular_map_sampler),
											UV_SPECULAR( inPs.uv@value(uv_specular).xy ),
											texIndex_specularIdx ).@insertpiece( FresnelSwizzle );
		@end
	@else
		float metalness = material.F0.x;
		@property( specular_map )

		float3 ddd =  SampleSpecular( textureMaps@value( specular_map_idx ),
													  samplerState@value(specular_map_sampler),
													  UV_SPECULAR( inPs.uv@value(uv_specular).xy ),
													  texIndex_specularIdx ).xyz;
			ddd.g = ddd.r;
			ddd.b = ddd.r;
			pixelData.specular.xyz *= ddd;

		@end
		pixelData.F0 = lerp( make_float_fresnel( 0.03f ), pixelData.diffuse.xyz * 3.14159f, metalness );
		pixelData.diffuse.xyz = pixelData.diffuse.xyz - pixelData.diffuse.xyz * metalness;
		@property( hlms_alphablend || hlms_screen_space_refractions )
			pixelData.F0 *= material.F0.w; ///Should this be done for non-metallic as well???
		@end
	@end
	@property( transparent_mode || hlms_screen_space_refractions )
		pixelData.F0 *= pixelData.diffuse.w;
	@end
@end

4、 pbr材质中的漫反射贴图不可以全黑或者过黑,也就是像素的亮度接近于0,在shader中我们可以看到, 基本所有漫反射(环境光、漫反射光)相关的材质都会乘以漫反射贴图的颜色,所以如果贴图颜色过暗则直接导致物体显示偏暗,另外漫反射贴图也不可出现高对比度。否则亮的部分在强光下容易过度曝光导致发白。所以漫反射贴图一定要亮度适中,避免高对比度。

ogre-next吃鸡笔记_第1张图片ogre-next吃鸡笔记_第2张图片

上左图中暗部无法被任何光源照亮,右图为ps增加亮度后的结果

更多Ogre学习交流,欢迎加Q群:26自36己25去掉570

你可能感兴趣的:(Ogre,ogre,游戏引擎)