bool ETHRenderEntity::DrawProjShadow(const float maxHeight, const float minHeight, const ETHSceneProperties& sceneProps, const ETHLight& light, ETHSpriteEntity *pParent, const bool maxOpacity, const bool drawToTarget, const float targetAngle, const Vector3& v3TargetPos) { if (!m_pSprite || IsHidden()) return false; VideoPtr video = m_provider->GetVideo(); ETHShaderManagerPtr shaderManager = m_provider->GetShaderManager(); SpritePtr pShadow = shaderManager->GetProjShadow(); Vector3 v3LightPos; Vector3 v3ParentPos(0,0,0); const Vector3 v3EntityPos = GetPosition(); if (pParent) { v3ParentPos = pParent->GetPosition(); v3LightPos = Vector3(v3ParentPos.x, v3ParentPos.y, 0) + light.pos; } else { v3LightPos = light.pos; } // if the object is higher than the light, then the shadow shouldn't be cast on the floor if (v3LightPos.z < v3EntityPos.z) { return true; } const float scale = (m_properties.shadowScale <= 0.0f) ? 1.0f : m_properties.shadowScale; const float opacity = (m_properties.shadowOpacity <= 0.0f) ? 1.0f : m_properties.shadowOpacity; const Vector2 v2Size = GetCurrentSize(); Vector2 v2ShadowSize(v2Size.x, v2Size.y); Vector2 v2ShadowPos(v3EntityPos.x, v3EntityPos.y); // if we are drawing to a target of a rotated entity if (drawToTarget && targetAngle != 0) { // rotate the shadow position according to entity angle Matrix4x4 matRot = RotateZ(-DegreeToRadian(targetAngle)); Vector3 newShadowPos(v2ShadowPos, 0); newShadowPos = newShadowPos - v3TargetPos; newShadowPos = Multiply(newShadowPos, matRot); newShadowPos = newShadowPos + v3TargetPos; v2ShadowPos.x = newShadowPos.x; v2ShadowPos.y = newShadowPos.y; // rotate the light source to cast it correctly Vector3 newPos = v3LightPos - v3TargetPos; newPos = Multiply(newPos, matRot); v3LightPos = newPos + v3TargetPos; } Vector3 diff = v3EntityPos - v3LightPos; const float squaredDist = DP3(diff, diff); float squaredRange = light.range * light.range; if (squaredDist > squaredRange) { return true; } v2ShadowSize.x *= _ETH_SHADOW_SCALEX * scale; // calculate the correct shadow lenght according to the light height if ((GetPosition().z+v2Size.y) < light.pos.z) // if the light is over the entity { const float planarDist = Distance(GetPositionXY(), ETHGlobal::ToVector2(v3LightPos)); const float verticalDist = Abs((v3EntityPos.z+v2Size.y)-v3LightPos.z); const float totalDist = (planarDist/verticalDist)*Abs(v3LightPos.z); v2ShadowSize.y = totalDist-planarDist; // clamp shadow lenght to the object's height. This is not realistic // but it looks better for the real-time shadows. v2ShadowSize.y = Min(v2Size.y*_ETH_SHADOW_FAKE_STRETCH, v2ShadowSize.y); } else { v2ShadowSize.y *= ((drawToTarget) ? _ETH_SHADOW_SCALEY : _ETH_SHADOW_SCALEY/4); } // specify a minimum length for the shadow v2ShadowSize.y = Max(v2ShadowSize.y, v2Size.y); ShaderPtr pVS = video->GetVertexShader(); pVS->SetConstant(GS_L("shadowLength"), v2ShadowSize.y * m_properties.shadowLengthScale); pVS->SetConstant(GS_L("entityZ"), Max(m_shadowZ, v3EntityPos.z)); pVS->SetConstant(GS_L("shadowZ"), m_shadowZ); pVS->SetConstant(GS_L("lightPos"), v3LightPos); video->SetSpriteDepth( (GetType() == ETH_VERTICAL) ? ETHGlobal::ComputeDepth(m_shadowZ, maxHeight, minHeight) : Max(0.0f, ComputeDepth(maxHeight, minHeight) - m_layrableMinimumDepth)); v2ShadowSize.y = 1.0f; Vector2 lightPos2(v3LightPos.x, v3LightPos.y); const float shadowAngle = ::GetAngle((lightPos2 - Vector2(v3EntityPos.x, v3EntityPos.y))) + DegreeToRadian(targetAngle); squaredRange = Max(squaredDist, squaredRange); float attenBias = 1; // adjust brightness according to ambient light if (!maxOpacity) { attenBias = (1-(squaredDist/squaredRange)); //fade the color according to the light brightness const float colorLen = Max(Max(light.color.x, light.color.y), light.color.z); attenBias *= Min(colorLen, 1.0f); //fade the color according to the ambient light brightness const Vector3 &ambientColor = sceneProps.ambient; const float ambientColorLen = 1.0f-((ambientColor.x + ambientColor.y + ambientColor.z)/3.0f); attenBias = Min(attenBias*ambientColorLen, 1.0f); attenBias *= Max(Min((1-(GetPosition().z/Max(GetCurrentSize().y, 1.0f))), 1.0f), 0.0f); } GS_BYTE alpha = static_cast<GS_BYTE>(attenBias*255.0f*opacity); if (alpha < 8) return true; GS_COLOR dwShadowColor(alpha,255,255,255); pShadow->SetOrigin(Vector2(0.5f, 0.79f)); pShadow->SetRectMode(GSRM_THREE_TRIANGLES); pShadow->DrawShaped(v2ShadowPos, v2ShadowSize, dwShadowColor, dwShadowColor, dwShadowColor, dwShadowColor, RadianToDegree(shadowAngle)); return true; }
void gen8_vec4_generator::generate_vec4_instruction(vec4_instruction *instruction, struct brw_reg dst, struct brw_reg *src) { vec4_instruction *ir = (vec4_instruction *) instruction; if (dst.width == BRW_WIDTH_4) { /* This happens in attribute fixups for "dual instanced" geometry * shaders, since they use attributes that are vec4's. Since the exec * width is only 4, it's essential that the caller set * force_writemask_all in order to make sure the instruction is executed * regardless of which channels are enabled. */ assert(ir->force_writemask_all); /* Fix up any <8;8,1> or <0;4,1> source registers to <4;4,1> to satisfy * the following register region restrictions (from Graphics BSpec: * 3D-Media-GPGPU Engine > EU Overview > Registers and Register Regions * > Register Region Restrictions) * * 1. ExecSize must be greater than or equal to Width. * * 2. If ExecSize = Width and HorzStride != 0, VertStride must be set * to Width * HorzStride." */ for (int i = 0; i < 3; i++) { if (src[i].file == BRW_GENERAL_REGISTER_FILE) src[i] = stride(src[i], 4, 4, 1); } } switch (ir->opcode) { case BRW_OPCODE_MOV: MOV(dst, src[0]); break; case BRW_OPCODE_ADD: ADD(dst, src[0], src[1]); break; case BRW_OPCODE_MUL: MUL(dst, src[0], src[1]); break; case BRW_OPCODE_MACH: MACH(dst, src[0], src[1]); break; case BRW_OPCODE_MAD: MAD(dst, src[0], src[1], src[2]); break; case BRW_OPCODE_FRC: FRC(dst, src[0]); break; case BRW_OPCODE_RNDD: RNDD(dst, src[0]); break; case BRW_OPCODE_RNDE: RNDE(dst, src[0]); break; case BRW_OPCODE_RNDZ: RNDZ(dst, src[0]); break; case BRW_OPCODE_AND: AND(dst, src[0], src[1]); break; case BRW_OPCODE_OR: OR(dst, src[0], src[1]); break; case BRW_OPCODE_XOR: XOR(dst, src[0], src[1]); break; case BRW_OPCODE_NOT: NOT(dst, src[0]); break; case BRW_OPCODE_ASR: ASR(dst, src[0], src[1]); break; case BRW_OPCODE_SHR: SHR(dst, src[0], src[1]); break; case BRW_OPCODE_SHL: SHL(dst, src[0], src[1]); break; case BRW_OPCODE_CMP: CMP(dst, ir->conditional_mod, src[0], src[1]); break; case BRW_OPCODE_SEL: SEL(dst, src[0], src[1]); break; case BRW_OPCODE_DPH: DPH(dst, src[0], src[1]); break; case BRW_OPCODE_DP4: DP4(dst, src[0], src[1]); break; case BRW_OPCODE_DP3: DP3(dst, src[0], src[1]); break; case BRW_OPCODE_DP2: DP2(dst, src[0], src[1]); break; case BRW_OPCODE_F32TO16: /* Emulate the Gen7 zeroing bug. */ MOV(retype(dst, BRW_REGISTER_TYPE_UD), brw_imm_ud(0u)); MOV(retype(dst, BRW_REGISTER_TYPE_HF), src[0]); break; case BRW_OPCODE_F16TO32: MOV(dst, retype(src[0], BRW_REGISTER_TYPE_HF)); break; case BRW_OPCODE_LRP: LRP(dst, src[0], src[1], src[2]); break; case BRW_OPCODE_BFREV: /* BFREV only supports UD type for src and dst. */ BFREV(retype(dst, BRW_REGISTER_TYPE_UD), retype(src[0], BRW_REGISTER_TYPE_UD)); break; case BRW_OPCODE_FBH: /* FBH only supports UD type for dst. */ FBH(retype(dst, BRW_REGISTER_TYPE_UD), src[0]); break; case BRW_OPCODE_FBL: /* FBL only supports UD type for dst. */ FBL(retype(dst, BRW_REGISTER_TYPE_UD), src[0]); break; case BRW_OPCODE_CBIT: /* CBIT only supports UD type for dst. */ CBIT(retype(dst, BRW_REGISTER_TYPE_UD), src[0]); break; case BRW_OPCODE_ADDC: ADDC(dst, src[0], src[1]); break; case BRW_OPCODE_SUBB: SUBB(dst, src[0], src[1]); break; case BRW_OPCODE_BFE: BFE(dst, src[0], src[1], src[2]); break; case BRW_OPCODE_BFI1: BFI1(dst, src[0], src[1]); break; case BRW_OPCODE_BFI2: BFI2(dst, src[0], src[1], src[2]); break; case BRW_OPCODE_IF: IF(ir->predicate); break; case BRW_OPCODE_ELSE: ELSE(); break; case BRW_OPCODE_ENDIF: ENDIF(); break; case BRW_OPCODE_DO: DO(); break; case BRW_OPCODE_BREAK: BREAK(); break; case BRW_OPCODE_CONTINUE: CONTINUE(); break; case BRW_OPCODE_WHILE: WHILE(); break; case SHADER_OPCODE_RCP: MATH(BRW_MATH_FUNCTION_INV, dst, src[0]); break; case SHADER_OPCODE_RSQ: MATH(BRW_MATH_FUNCTION_RSQ, dst, src[0]); break; case SHADER_OPCODE_SQRT: MATH(BRW_MATH_FUNCTION_SQRT, dst, src[0]); break; case SHADER_OPCODE_EXP2: MATH(BRW_MATH_FUNCTION_EXP, dst, src[0]); break; case SHADER_OPCODE_LOG2: MATH(BRW_MATH_FUNCTION_LOG, dst, src[0]); break; case SHADER_OPCODE_SIN: MATH(BRW_MATH_FUNCTION_SIN, dst, src[0]); break; case SHADER_OPCODE_COS: MATH(BRW_MATH_FUNCTION_COS, dst, src[0]); break; case SHADER_OPCODE_POW: MATH(BRW_MATH_FUNCTION_POW, dst, src[0], src[1]); break; case SHADER_OPCODE_INT_QUOTIENT: MATH(BRW_MATH_FUNCTION_INT_DIV_QUOTIENT, dst, src[0], src[1]); break; case SHADER_OPCODE_INT_REMAINDER: MATH(BRW_MATH_FUNCTION_INT_DIV_REMAINDER, dst, src[0], src[1]); break; case SHADER_OPCODE_TEX: case SHADER_OPCODE_TXD: case SHADER_OPCODE_TXF: case SHADER_OPCODE_TXF_CMS: case SHADER_OPCODE_TXF_MCS: case SHADER_OPCODE_TXL: case SHADER_OPCODE_TXS: case SHADER_OPCODE_TG4: case SHADER_OPCODE_TG4_OFFSET: generate_tex(ir, dst); break; case VS_OPCODE_URB_WRITE: generate_urb_write(ir, true); break; case SHADER_OPCODE_GEN4_SCRATCH_READ: generate_scratch_read(ir, dst, src[0]); break; case SHADER_OPCODE_GEN4_SCRATCH_WRITE: generate_scratch_write(ir, dst, src[0], src[1]); break; case VS_OPCODE_PULL_CONSTANT_LOAD: case VS_OPCODE_PULL_CONSTANT_LOAD_GEN7: generate_pull_constant_load(ir, dst, src[0], src[1]); break; case GS_OPCODE_URB_WRITE: generate_urb_write(ir, false); break; case GS_OPCODE_THREAD_END: generate_gs_thread_end(ir); break; case GS_OPCODE_SET_WRITE_OFFSET: generate_gs_set_write_offset(dst, src[0], src[1]); break; case GS_OPCODE_SET_VERTEX_COUNT: generate_gs_set_vertex_count(dst, src[0]); break; case GS_OPCODE_SET_DWORD_2_IMMED: generate_gs_set_dword_2_immed(dst, src[0]); break; case GS_OPCODE_PREPARE_CHANNEL_MASKS: generate_gs_prepare_channel_masks(dst); break; case GS_OPCODE_SET_CHANNEL_MASKS: generate_gs_set_channel_masks(dst, src[0]); break; case SHADER_OPCODE_SHADER_TIME_ADD: assert(!"XXX: Missing Gen8 vec4 support for INTEL_DEBUG=shader_time"); break; case SHADER_OPCODE_UNTYPED_ATOMIC: generate_untyped_atomic(ir, dst, src[0], src[1]); break; case SHADER_OPCODE_UNTYPED_SURFACE_READ: generate_untyped_surface_read(ir, dst, src[0]); break; case VS_OPCODE_UNPACK_FLAGS_SIMD4X2: assert(!"VS_OPCODE_UNPACK_FLAGS_SIMD4X2 should not be used on Gen8+."); break; default: if (ir->opcode < (int) ARRAY_SIZE(opcode_descs)) { _mesa_problem(ctx, "Unsupported opcode in `%s' in VS\n", opcode_descs[ir->opcode].name); } else { _mesa_problem(ctx, "Unsupported opcode %d in VS", ir->opcode); } abort(); } }