轻量封装WebGPU渲染系统示例<11>- WebGPU简单PBR效果(源码)

news2024/11/26 18:30:55

当前示例源码github地址:

https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/SimplePBRTest.ts

此示例渲染系统实现的特性:

1. 用户态与系统态隔离。

         细节请见:引擎系统设计思路 - 用户态与系统态隔离-CSDN博客

2. 高频调用与低频调用隔离。

3. 面向用户的易用性封装。

4. 渲染数据(内外部相关资源)和渲染机制分离。

5. 用户操作和渲染系统调度并行机制。

6. 数据/语义驱动。

当前示例运行效果:

顶点shader:


@group(0) @binding(0) var<uniform> objMat : mat4x4<f32>;
@group(0) @binding(1) var<uniform> viewMat : mat4x4<f32>;
@group(0) @binding(2) var<uniform> projMat : mat4x4<f32>;

struct VertexOutput {
  @builtin(position) Position : vec4<f32>,
  @location(0) pos: vec4<f32>,
  @location(1) uv : vec2<f32>,
  @location(2) normal : vec3<f32>,
  @location(3) camPos : vec3<f32>
}

fn inverseM33(m: mat3x3<f32>)-> mat3x3<f32> {
    let a00 = m[0][0]; let a01 = m[0][1]; let a02 = m[0][2];
    let a10 = m[1][0]; let a11 = m[1][1]; let a12 = m[1][2];
    let a20 = m[2][0]; let a21 = m[2][1]; let a22 = m[2][2];
    let b01 = a22 * a11 - a12 * a21;
    let b11 = -a22 * a10 + a12 * a20;
    let b21 = a21 * a10 - a11 * a20;
    let det = a00 * b01 + a01 * b11 + a02 * b21;
    return mat3x3<f32>(
		vec3<f32>(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11)) / det,
                vec3<f32>(b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10)) / det,
                vec3<f32>(b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det);
}
fn m44ToM33(m: mat4x4<f32>) -> mat3x3<f32> {
	return mat3x3(m[0].xyz, m[1].xyz, m[2].xyz);
}

fn inverseM44(m: mat4x4<f32>)-> mat4x4<f32> {
    let a00 = m[0][0]; let a01 = m[0][1]; let a02 = m[0][2]; let a03 = m[0][3];
    let a10 = m[1][0]; let a11 = m[1][1]; let a12 = m[1][2]; let a13 = m[1][3];
    let a20 = m[2][0]; let a21 = m[2][1]; let a22 = m[2][2]; let a23 = m[2][3];
    let a30 = m[3][0]; let a31 = m[3][1]; let a32 = m[3][2]; let a33 = m[3][3];
    let b00 = a00 * a11 - a01 * a10;
    let b01 = a00 * a12 - a02 * a10;
    let b02 = a00 * a13 - a03 * a10;
    let b03 = a01 * a12 - a02 * a11;
    let b04 = a01 * a13 - a03 * a11;
    let b05 = a02 * a13 - a03 * a12;
    let b06 = a20 * a31 - a21 * a30;
    let b07 = a20 * a32 - a22 * a30;
    let b08 = a20 * a33 - a23 * a30;
    let b09 = a21 * a32 - a22 * a31;
    let b10 = a21 * a33 - a23 * a31;
    let b11 = a22 * a33 - a23 * a32;
    let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
	return mat4x4<f32>(
		vec4<f32>(a11 * b11 - a12 * b10 + a13 * b09,
		a02 * b10 - a01 * b11 - a03 * b09,
		a31 * b05 - a32 * b04 + a33 * b03,
		a22 * b04 - a21 * b05 - a23 * b03) / det,
			vec4<f32>(a12 * b08 - a10 * b11 - a13 * b07,
		a00 * b11 - a02 * b08 + a03 * b07,
		a32 * b02 - a30 * b05 - a33 * b01,
		a20 * b05 - a22 * b02 + a23 * b01) / det,
		vec4<f32>(a10 * b10 - a11 * b08 + a13 * b06,
		a01 * b08 - a00 * b10 - a03 * b06,
		a30 * b04 - a31 * b02 + a33 * b00,
		a21 * b02 - a20 * b04 - a23 * b00) / det,
		vec4<f32>(a11 * b07 - a10 * b09 - a12 * b06,
		a00 * b09 - a01 * b07 + a02 * b06,
		a31 * b01 - a30 * b03 - a32 * b00,
		a20 * b03 - a21 * b01 + a22 * b00) / det);
}
@vertex
fn main(
  @location(0) position : vec3<f32>,
  @location(1) uv : vec2<f32>,
  @location(2) normal : vec3<f32>
) -> VertexOutput {
  let wpos = objMat * vec4(position.xyz, 1.0);
  var output : VertexOutput;
  output.Position = projMat * viewMat * wpos;
  output.uv = uv;

  let invMat33 = inverseM33( m44ToM33( objMat ) );
  output.normal = normalize( normal * invMat33 );
  output.camPos = (inverseM44(viewMat) * vec4<f32>(0.0,0.0,0.0, 1.0)).xyz;
  output.pos = wpos;
  return output;
}

片段shader:

@group(0) @binding(3) var<storage> albedo: vec4f;
@group(0) @binding(4) var<storage> param: vec4f;

const PI = 3.141592653589793;
const PI2 = 6.283185307179586;
const PI_HALF = 1.5707963267948966;
const RECIPROCAL_PI = 0.3183098861837907;
const RECIPROCAL_PI2 = 0.15915494309189535;
const EPSILON = 1e-6;

fn approximationSRGBToLinear(srgbColor: vec3<f32>) -> vec3<f32> {
    return pow(srgbColor, vec3<f32>(2.2));
}
fn approximationLinearToSRCB(linearColor: vec3<f32>) -> vec3<f32> {
    return pow(linearColor, vec3(1.0/2.2));
}

fn accurateSRGBToLinear(srgbColor: vec3<f32>) -> vec3<f32> {
    let linearRGBLo = srgbColor / 12.92;
    let linearRGBHi = pow((srgbColor + vec3(0.055)) / vec3(1.055), vec3(2.4));
	if( all( srgbColor <= vec3(0.04045) ) ) {
		return linearRGBLo;
	}
    return linearRGBHi;
}
fn accurateLinearToSRGB(linearColor: vec3<f32>) -> vec3<f32> {
    let srgbLo = linearColor * 12.92;
    let srgbHi = (pow(abs(linearColor), vec3(1.0 / 2.4)) * 1.055) - 0.055;
    if(all(linearColor <= vec3(0.0031308))) {
		return srgbLo;
	}
    return srgbHi;
}

// Trowbridge-Reitz(Generalized-Trowbridge-Reitz,GTR)
fn DistributionGTR1(NdotH: f32, roughness: f32) -> f32 {
    if (roughness >= 1.0) {
		return 1.0/PI;
	}
    let a2 = roughness * roughness;
    let t = 1.0 + (a2 - 1.0)*NdotH*NdotH;
    return (a2 - 1.0) / (PI * log(a2) *t);
}
fn DistributionGTR2(NdotH: f32, roughness: f32) -> f32 {
    let a2 = roughness * roughness;
    let t = 1.0 + (a2 - 1.0) * NdotH * NdotH;
    return a2 / (PI * t * t);
}


fn DistributionGGX(N: vec3<f32>, H: vec3<f32>, roughness: f32) -> f32 {
    let a = roughness*roughness;
    let a2 = a*a;
    let NdotH = max(dot(N, H), 0.0);
    let NdotH2 = NdotH*NdotH;

    let nom   = a2;
    var denom = (NdotH2 * (a2 - 1.0) + 1.0);
    denom = PI * denom * denom;

    return nom / max(denom, 0.0000001); // prevent divide by zero for roughness=0.0 and NdotH=1.0
}


fn GeometryImplicit(NdotV: f32, NdotL: f32) -> f32 {
    return NdotL * NdotV;
}

// ----------------------------------------------------------------------------
fn GeometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 {
    let r = (roughness + 1.0);
    let k = (r*r) / 8.0;

    let nom   = NdotV;
    let denom = NdotV * (1.0 - k) + k;

    return nom / denom;
}
// ----------------------------------------------------------------------------
fn GeometrySmith(N: vec3<f32>, V: vec3<f32>, L: vec3<f32>, roughness: f32) -> f32 {
    let NdotV = max(dot(N, V), 0.0);
    let NdotL = max(dot(N, L), 0.0);
    let ggx2 = GeometrySchlickGGX(NdotV, roughness);
    let ggx1 = GeometrySchlickGGX(NdotL, roughness);

    return ggx1 * ggx2;
}

// @param cosTheta is clamp(dot(H, V), 0.0, 1.0)
fn fresnelSchlick(cosTheta: f32, F0: vec3<f32>) -> vec3<f32> {
    return F0 + (1.0 - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0);
}
fn fresnelSchlick2(specularColor: vec3<f32>, L: vec3<f32>, H: vec3<f32>) -> vec3<f32> {
   return specularColor + (1.0 - specularColor) * pow(1.0 - saturate(dot(L, H)), 5.0);
}
//fresnelSchlick2(specularColor, L, H) * ((SpecularPower + 2) / 8 ) * pow(saturate(dot(N, H)), SpecularPower) * dotNL;

const OneOnLN2_x6 = 8.656171;// == 1/ln(2) * 6 (6 is SpecularPower of 5 + 1)
// dot -> dot(N,V) or
fn fresnelSchlick3(specularColor: vec3<f32>, dot: f32, glossiness: f32) -> vec3<f32> {
	return specularColor + (max(vec3(glossiness), specularColor) - specularColor) * exp2(-OneOnLN2_x6 * dot);
}
fn fresnelSchlickWithRoughness(specularColor: vec3<f32>, L: vec3<f32>, N: vec3<f32>, gloss: f32) -> vec3<f32> {
   return specularColor + (max(vec3(gloss), specularColor) - specularColor) * pow(1.0 - saturate(dot(L, N)), 5.0);
}

const A = 2.51f;
const B = 0.03f;
const C = 2.43f;
const D = 0.59f;
const E = 0.14f;
fn ACESToneMapping(color: vec3<f32>, adapted_lum: f32) -> vec3<f32> {

	let c = color * adapted_lum;
	return (c * (A * c + B)) / (c * (C * c + D) + E);
}

//color = color / (color + vec3(1.0));
fn reinhard(v: vec3<f32>) -> vec3<f32> {
    return v / (vec3<f32>(1.0) + v);
}
fn reinhard_extended(v: vec3<f32>, max_white: f32) -> vec3<f32> {
    let numerator = v * (1.0f + (v / vec3(max_white * max_white)));
    return numerator / (1.0f + v);
}
fn luminance(v: vec3<f32>) -> f32 {
    return dot(v, vec3<f32>(0.2126f, 0.7152f, 0.0722f));
}

fn change_luminance(c_in: vec3<f32>, l_out: f32) -> vec3<f32> {
    let l_in = luminance(c_in);
    return c_in * (l_out / l_in);
}
fn reinhard_extended_luminance(v: vec3<f32>, max_white_l: f32) -> vec3<f32> {
    let l_old = luminance(v);
    let numerator = l_old * (1.0f + (l_old / (max_white_l * max_white_l)));
    let l_new = numerator / (1.0f + l_old);
    return change_luminance(v, l_new);
}
fn ReinhardToneMapping( color: vec3<f32>, toneMappingExposure: f32 ) -> vec3<f32> {

	let c = color * toneMappingExposure;
	return saturate( c / ( vec3( 1.0 ) + c ) );

}
// expects values in the range of [0,1]x[0,1], returns values in the [0,1] range.
// do not collapse into a single function per: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
const highp_a = 12.9898;
const highp_b = 78.233;
const highp_c = 43758.5453;
fn rand( uv: vec2<f32> ) -> f32 {
	let dt = dot( uv.xy, vec2<f32>( highp_a, highp_b ) );
	let sn = modf( dt / PI ).fract;
	return fract(sin(sn) * highp_c);
}
// // based on https://www.shadertoy.com/view/MslGR8
fn dithering( color: vec3<f32>, fragCoord: vec2<f32> ) -> vec3<f32> {
    //Calculate grid position
    let grid_position = rand( fragCoord );

    //Shift the individual colors differently, thus making it even harder to see the dithering pattern
    var dither_shift_RGB = vec3<f32>( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );

    //modify shift acording to grid position.
    dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );

    //shift the color by dither_shift
    return color + dither_shift_RGB;
}

const dis = 700.0;
const disZ = 400.0;
const u_lightPositions = array<vec3<f32>, 4>(
	vec3<f32>(-dis, dis, disZ),
	vec3<f32>(dis, dis, disZ),
	vec3<f32>(-dis, -dis, disZ),
	vec3<f32>(dis, -dis, disZ)
);
const colorValue = 300.0;
const u_lightColors = array<vec3<f32>, 4>(
	vec3<f32>(colorValue, colorValue, colorValue),
	vec3<f32>(colorValue, colorValue, colorValue),
	vec3<f32>(colorValue, colorValue, colorValue),
	vec3<f32>(colorValue, colorValue, colorValue),
);

fn calcPBRColor3(Normal: vec3<f32>, WorldPos: vec3<f32>, camPos: vec3<f32>) -> vec3<f32> {

	var color = vec3<f32>(0.0);

    var ao = param.x;
    var roughness = param.y;
    var metallic = param.z;

	var N = normalize(Normal);
    var V = normalize(camPos.xyz - WorldPos);
    var dotNV = clamp(dot(N, V), 0.0, 1.0);

    // calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
    // of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
    var F0 = vec3(0.04);
    F0 = mix(F0, albedo.xyz, metallic);

    // reflectance equation
    var Lo = vec3(0.0);
    
	for (var i: i32 = 0; i < 4; i++) {
		// calculate per-light radiance
        let L = normalize(u_lightPositions[i].xyz - WorldPos);
        let H = normalize(V + L);
        let distance = length(u_lightPositions[i].xyz - WorldPos);

        let attenuation = 1.0 / (1.0 + 0.001 * distance + 0.0003 * distance * distance);
        let radiance = u_lightColors[i].xyz * attenuation;

        // Cook-Torrance BRDF
        let NDF = DistributionGGX(N, H, roughness);
        let G   = GeometrySmith(N, V, L, roughness);
        //vec3 F    = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
        let F    = fresnelSchlick3(F0,clamp(dot(H, V), 0.0, 1.0), 0.9);
        //vec3 F    = fresnelSchlick3(F0,dotNV, 0.9);

        let nominator    = NDF * G * F;
        let denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0);
        let specular = nominator / max(denominator, 0.001); // prevent divide by zero for NdotV=0.0 or NdotL=0.0

        // kS is equal to Fresnel
        let kS = F;
        // for energy conservation, the diffuse and specular light can't
        // be above 1.0 (unless the surface emits light); to preserve this
        // relationship the diffuse component (kD) should equal 1.0 - kS.
        var kD = vec3<f32>(1.0) - kS;
        // multiply kD by the inverse metalness such that only non-metals
        // have diffuse lighting, or a linear blend if partly metal (pure metals
        // have no diffuse light).
        kD *= 1.0 - metallic;

        // scale light by NdotL
        let NdotL = max(dot(N, L), 0.0);

        // add to outgoing radiance Lo
        // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
        Lo += (kD * albedo.xyz / PI + specular) * radiance * NdotL;
	}
	// ambient lighting (note that the next IBL tutorial will replace
    // this ambient lighting with environment lighting).
    let ambient = vec3<f32>(0.03) * albedo.xyz * ao;

    color = ambient + Lo;
    // HDR tonemapping
    color = reinhard( color );
    // gamma correct
    color = pow(color, vec3<f32>(1.0/2.2));
	return color;
}

@fragment
fn main(
  @location(0) pos: vec4<f32>,
  @location(1) uv: vec2<f32>,
  @location(2) normal: vec3<f32>,
  @location(3) camPos: vec3<f32>
) -> @location(0) vec4<f32> {
  var color4 = vec4(calcPBRColor3(normal, pos.xyz, camPos), 1.0);
  return color4;
}

此示例基于此渲染系统实现,当前示例TypeScript源码如下

export class SimplePBRTest {

	private mRscene = new RendererScene();

	geomData = new GeomDataBuilder();

	initialize(): void {
		console.log("SimplePBRTest::initialize() ...");

		const rc = this.mRscene;
		rc.initialize();
		this.initEvent();
		this.initScene();
	}
	private initEvent(): void {
		const rc = this.mRscene;
		rc.addEventListener(MouseEvent.MOUSE_DOWN, this.mouseDown);
		new MouseInteraction().initialize(rc, 0, false).setAutoRunning(true);
	}

	private mouseDown = (evt: MouseEvent): void => {

	}
	private createMaterial(shdSrc: WGRShderSrcType, color?: Color4, arm?: number[]): WGMaterial {

		color = color ? color : new Color4();

		let pipelineDefParam = {
			depthWriteEnabled: true,
			blendModes: [] as string[]
		};

		const material = new WGMaterial({
			shadinguuid: "simple-pbr-materialx",
			shaderCodeSrc: shdSrc,
			pipelineDefParam
		});

		let albedoV = new WGRStorageValue(new Float32Array([color.r, color.g, color.b, 1]));

		// arm[0]: ao, arm[1]: roughness, arm[2]: metallic
		let armV = new WGRStorageValue(new Float32Array([arm[0], arm[1], arm[2], 1]));
		material.uniformValues = [albedoV, armV];

		return material;
	}

	private createGeom(rgd: GeomRDataType, normalEnabled = false): WGGeometry {

		const geometry = new WGGeometry()
			.addAttribute({ position: rgd.vs })
			.addAttribute({ uv: rgd.uvs })
			.setIndices(rgd.ivs);
		if (normalEnabled) {
			geometry.addAttribute({ normal: rgd.nvs });
		}
		return geometry;
	}
	private initScene(): void {

		const rc = this.mRscene;
		const geometry = this.createGeom(this.geomData.createSphere(50), true);

		const shdSrc = {
			vertShaderSrc: { code: vertWGSL, uuid: "vertShdCode" },
			fragShaderSrc: { code: fragWGSL, uuid: "fragShdCode" }
		};

		let tot = 5;
		const size = new Vector3(150, 150, 150);
		const pos = new Vector3().copyFrom(size).scaleBy(-0.5 * (tot - 1));
		let pv = new Vector3();
		for (let i = 0; i < tot; ++i) {
			for (let j = 0; j < tot; ++j) {
				// params[0]: ao, params[1]: roughness, params[2]: metallic
				let params = [1.5, (i / tot) * 0.95 + 0.05, (j / tot) * 0.95 + 0.05];
				let material = this.createMaterial(shdSrc, new Color4(0.5, 0.0, 0.0), params);
				let entity = new Entity3D();
				entity.materials = [material];
				entity.geometry = geometry;
				pv.setXYZ(i * size.x, j * size.y, size.z).addBy(pos);
				entity.transform.setPosition(pv);
				rc.addEntity(entity);
			}
		}
	}

	run(): void {
		this.mRscene.run();
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1162310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

爆肝整理,Fiddler+Charles+Chrome开发者工具弱网测试总结,一篇概全...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、Fiddler模拟弱…

​国网、首钢集团、施耐德、吉利等出席2023中国企业绿电国际峰会​

2023中国企业绿电国际峰会将通过邀请国家发展和改革委员会能源研究所、国网能源研究院、落基山研究所、首钢集团技术研究院、远景集团、施耐德电气、有色金属技术经济研究院有限责任公司、上海电气储能、博世、巴斯夫、晶科能源、吉利汽车等领域的企业高管&#xff0c;从绿色电…

跨境电商五大运营模式都有哪些?有何特点?

在跨境电商高速发展之下&#xff0c;跨境电商平台数量不断增加&#xff0c;各种跨境电商模式也不断逐渐暴露在人们的视野&#xff0c;下面小编就来为大家分析分析这些跨境电商都有哪些&#xff0c;它们的特点又是哪些&#xff0c;快来一起了解了解吧! 一、跨境电商五大运营模式…

第二证券:43家上市券商三季报拆解

受生意、投行、自营三大业务“滑坡”影响&#xff0c;本年三季度&#xff0c;上市券商的运营成果略有“退让”。 根据Wind计算数据&#xff0c;本年第三季度&#xff0c;43家上市券商估计完结运营收入1127.37亿元&#xff0c;同比下降9.7%&#xff1b;归母净流润280.51亿元&am…

办公必备神器:如何用AI快速生成年终总结PPT?

2023年已经步入尾声&#xff0c;今年的销售业绩如何&#xff1f;用户同比增长率是否达到预期&#xff1f;部门年度API完成情况&#xff1f;新开发的项目进展如何&#xff1f;品牌全球计划在各区域市场的部署进展&#xff1f;…… 每年年底&#xff0c;不论是纵横全球的大企业&…

【Linux基础IO篇】系统文件接口(1)

【Linux基础IO篇】系统文件接口&#xff08;1&#xff09; 目录 【Linux基础IO篇】系统文件接口&#xff08;1&#xff09;回顾C语言的文件接口系统文件I/Oopen接口的介绍 open函数返回值文件描述符fd&#xff08;小整数&#xff09;文件描述符的分配规则 重定向dup2系统调用改…

大模型训练时的内存泄漏与显存不足

内存泄漏位置 位置1 FaceDetection 不可重复创建FaceDetection&#xff0c;该位置是内存泄漏的大头 mediapipe.solutions.face_detection.FaceDetection(model_selection1, min_detection_confidence0.5)位置2 tensorboardX 不可重复创建 tensorboardX.SummaryWriter Summ…

2023年新疆电气年会-安科瑞 蒋静

2023年新疆电气年会于10月12-13日在五家渠市五家渠青湖御园酒店隆重召开。安科瑞电气股份有限公司受邀参会&#xff0c;为大会带来了主题演讲和产品现场展示&#xff01; 大会以“绿色低碳、智慧新疆”主题&#xff0c;分为专题学术报告、工程信息交流、论文颁奖、产品展示等环…

基于Vite使用VitePress搭建静态站点博客

使用VitePress搭建静态站点博客 官方文档什么是VitePress&#xff1f;一、初始化项目1.安装依赖包VitePress可以单独使用&#xff0c;也可以安装到现有的项目中。在这两种情况下&#xff0c;您都可以安装它: (也可以全局安装&#xff0c;建议&#xff1a;当前项目内安装) 2.初始…

c语言思维框图

思维框图 文章目录 前言一、c语言思维框图总结 前言 附件为c语言思维框图。 一、c语言思维框图 后面可以增加更多框图&#xff0c;比如c/c学习路线图。 总结 提示&#xff1a;这里对文章进行总结&#xff1a; 例如&#xff1a;以上就是今天要讲的内容&#xff0c;本文仅仅简单…

Xilinx 产品制程工艺

A – 45nm 供货至2030年 Sparton6 xx 提供卓越的连接功能&#xff0c;例如高逻辑引脚比、小尺寸封装、MicroBlaze™ 软处理器&#xff0c;以及多种受支持的 I/O 协议。 B – 28nm 供货至2035年 spartan-7\artix-7 \kintex-7\virtex-7\Zynq™ 7000 SoC 工艺节点上的持续创新…

Python-市场交易中的概率夏普比率 (PSR)

“虽然偏度和峰度不会影响夏普比率的点估计,但它会极大地影响其置信带,从而影响其统计显着性”Bailey 和 Lpez de Prado 1 0. 简介 今天,我们将讨论备受推崇的夏普比率(SR),该指标几

野火霸天虎 STM32F407 学习笔记_2 寄存器介绍

寄存器 虽然正式编程没有必要用寄存器编程&#xff0c;通常都是库函数或者 hal 库。但是还是有必要学一下原理的。 寄存器映射 芯片视图如下。 丝印&#xff1a;芯片上印的信息。型号&#xff0c;内核&#xff0c;生产批次等。 引脚&#xff1a;左上角是有小圆点的&#x…

CH09_重新组织数据

拆分变量&#xff08;Split Variable&#xff09; 曾用名&#xff1a;移除对参数的赋值&#xff08;Remove Assignments to Parameters&#xff09; 曾用名&#xff1a;分解临时变量&#xff08;Split Temp&#xff09; let temp 2 * (height width); console.log(temp); t…

JVM——类的生命周期(加载阶段,连接阶段,初始化阶段)

目录 1.加载阶段2.连接阶段1.验证2.准备3.解析 3.初始化阶段4.总结 类的生命周期 1.加载阶段 ⚫ 1、加载(Loading)阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。 程序员可以使用Java代码拓展的不同的渠道。 ⚫ 2、类加载器在加载完类…

SAP 物料凭证在凭证流中显示归档

问题&#xff1a; 在交货单做过PGI/PGR之后&#xff0c;显示物料凭证已归档&#xff0c;但是实际上并不是人为归档 MIGO去显示物料凭证的时候显示不存在 VL09 无法冲销 如下图所示 原因&#xff1a;1.人为做了归档 2.在做PGI的时候出现了异常。导致出现了问题 解决…

本章内容的重点是对各种电子式电动机保护器电路的原理分析和故障维修指导,对电子式电动机保护器以下简称为电动机保护器。

上世纪八十年代之前&#xff0c;电子技术的应用尚处于初级阶段&#xff0c;对电动机的保护任务多由热继电器承担&#xff0c;国内型号为为JR20-XX系列、JR36-XX系列等。其保护机理如下&#xff1a;热继电器由发热元件、双金属片、触点及一套传动和调整机构组成。发热元件是一段…

react-hook-form。 useFieldArray Controller 必填,报错自动获取较多疑问记录

背景 动态多个数据Controller包裹时候&#xff0c;原生html标签input可以add时候自动获取焦点&#xff0c;聚焦到最近不符合要求的元素上面 matiral的TextField同样可以可是x-date-pickers/DatePicker不可以❌ 是什么原因呢&#xff0c;内部提供foucs&#xff1f;&#xff1f;属…

【C++】医学影像信息管理系统源码

狭义的医学影像信息系统是指基于医学影像存储和通信系统的管理系统&#xff0c;从技术上解决了影像处理技术。临床信息系统是指支持医院医务人员临床活动&#xff0c;收集和处理患者临床医疗信息的信息管理系统。放射科信息系统是指放射科挂号、分诊、影像诊断报告、信息查询、…

在Qt中解决opencv的putText函数无法绘制中文的一种解决方法

文章目录 1.问题2.查阅资料3.解决办法 1.问题 在opencv中&#xff0c;假如直接使用putText绘制中文&#xff0c;会在图像上出现问号&#xff0c;如下图所示&#xff1a; 2.查阅资料 查了一些资料&#xff0c;说想要解决这个问题&#xff0c;需要用到freetype库或者用opencv…