Версия Minecraft
1.12.2
476
9
39
Есть ли тема где можно тот или иной туториал попросить сделать?
Или может кто-то здесь ответит, тоже невероятно хорошо было бы.
Мучаюсь с Ambient Occlusion и гайдов на русском или почти нет, или уходят в свою реализацию, а мне бы понять, что в самом майне относительно кода происходит :\
А проблема в том, что все блоки чёрные, если я у всех делаю свою волнистую модельку.
В целом я понимаю со стороны логики как это работает, но как через кучу математических формул это происходит в коде AO хз
2018-03-31_23.21.18.png2018-03-31_23.38.42.png2018-03-31_23.38.47.png
Java:
    public void fillQuadBounds(IBlockState stateIn, int[] vertexData, EnumFacing face, @Nullable float[] faceShape, BitSet shapeState)
    {
        float west = 32.0F;
        float down = 32.0F;
        float north = 32.0F;
        float east = -32.0F;
        float up = -32.0F;
        float south = -32.0F;
  
        int count = vertexData.length / 4;
        for (int i = 0; i < vertexData.length / count; i++)
        {
            float posX = Float.intBitsToFloat(vertexData[i * 7]);
            float posY = Float.intBitsToFloat(vertexData[i * 7 + 1]);
            float posZ = Float.intBitsToFloat(vertexData[i * 7 + 2]);
            west = Math.min(west, posX);
            down = Math.min(down, posY);
            north = Math.min(north, posZ);
            east = Math.max(east, posX);
            up = Math.max(up, posY);
            south = Math.max(south, posZ);
        }
      
        if (faceShape != null)
        {
            faceShape[WEST.getIndex()] = west;
            faceShape[EAST.getIndex()] = east;
            faceShape[EnumFacing.DOWN.getIndex()] = down;
            faceShape[EnumFacing.UP.getIndex()] = up;
            faceShape[NORTH.getIndex()] = north;
            faceShape[SOUTH.getIndex()] = south;
            int countFace = EnumFacing.values().length;
            faceShape[WEST.getIndex() + countFace] = 1.0F - west;
            faceShape[EAST.getIndex() + countFace] = 1.0F - east;
            faceShape[EnumFacing.DOWN.getIndex() + countFace] = 1.0F - down;
            faceShape[EnumFacing.UP.getIndex() + countFace] = 1.0F - up;
            faceShape[NORTH.getIndex() + countFace] = 1.0F - north;
            faceShape[SOUTH.getIndex() + countFace] = 1.0F - south;
        }
      
        switch (face)
        {
            case DOWN:
                shapeState.set(1, west >= 1.0E-4F || north >= 1.0E-4F || east <= 0.9999F || south <= 0.9999F);
                shapeState.set(0, (down < 1.0E-4F || stateIn.isFullCube()) && down == up);
                break;
            case UP:
                shapeState.set(1, west >= 1.0E-4F || north >= 1.0E-4F || east <= 0.9999F || south <= 0.9999F);
                shapeState.set(0, (up > 0.9999F || stateIn.isFullCube()) && down == up);
                break;
            case NORTH:
                shapeState.set(1, west >= 1.0E-4F || down >= 1.0E-4F || east <= 0.9999F || up <= 0.9999F);
                shapeState.set(0, (north < 1.0E-4F || stateIn.isFullCube()) && north == south);
                break;
            case SOUTH:
                shapeState.set(1, west >= 1.0E-4F || down >= 1.0E-4F || east <= 0.9999F || up <= 0.9999F);
                shapeState.set(0, (south > 0.9999F || stateIn.isFullCube()) && north == south);
                break;
            case WEST:
                shapeState.set(1, down >= 1.0E-4F || north >= 1.0E-4F || up <= 0.9999F || south <= 0.9999F);
                shapeState.set(0, (west < 1.0E-4F || stateIn.isFullCube()) && west == east);
                break;
            case EAST:
                shapeState.set(1, down >= 1.0E-4F || north >= 1.0E-4F || up <= 0.9999F || south <= 0.9999F);
                shapeState.set(0, (east > 0.9999F || stateIn.isFullCube()) && west == east);
        }
    }
Java:
public class AmbientOcclusionFace
{
    public final float[] vertexColorMultiplier = new float[4];
    public final int[] vertexBrightness = new int[4];
 
    public void updateVertexBrightness(IBlockAccess worldIn, IBlockState state, BlockPos centerPos, EnumFacing direction, float[] faceShape, BitSet shapeState)
    {
        BlockPos posIn = shapeState.get(0) ? centerPos.offset(direction) : centerPos;
        BlockPos.PooledMutableBlockPos mutablePos = BlockPos.PooledMutableBlockPos.retain();
        BlockModelRenderer.EnumNeighborInfo neighborInfo = BlockModelRenderer.EnumNeighborInfo.getNeighbourInfo(direction);
        BlockPos.PooledMutableBlockPos mutablePos1 = BlockPos.PooledMutableBlockPos.retain(posIn).move(neighborInfo.corners[0]);
        BlockPos.PooledMutableBlockPos mutablePos2 = BlockPos.PooledMutableBlockPos.retain(posIn).move(neighborInfo.corners[1]);
        BlockPos.PooledMutableBlockPos mutablePos3 = BlockPos.PooledMutableBlockPos.retain(posIn).move(neighborInfo.corners[2]);
        BlockPos.PooledMutableBlockPos mutablePos4 = BlockPos.PooledMutableBlockPos.retain(posIn).move(neighborInfo.corners[3]);
        int light = state.getPackedLightmapCoords(worldIn, mutablePos1);
        int light1 = state.getPackedLightmapCoords(worldIn, mutablePos2);
        int light2 = state.getPackedLightmapCoords(worldIn, mutablePos3);
        int light3 = state.getPackedLightmapCoords(worldIn, mutablePos4);
        //if cube is normal 0.2f else 1.0f
        float occlusionValue = worldIn.getBlockState(mutablePos1).getAmbientOcclusionLightValue();
        float occlusionValue1 = worldIn.getBlockState(mutablePos2).getAmbientOcclusionLightValue();
        float occlusionValue2 = worldIn.getBlockState(mutablePos3).getAmbientOcclusionLightValue();
        float occlusionValue3 = worldIn.getBlockState(mutablePos4).getAmbientOcclusionLightValue();
        boolean isTranslucent = worldIn.getBlockState(mutablePos.setPos(mutablePos1).move(direction)).isTranslucent();
        boolean isTranslucent1 = worldIn.getBlockState(mutablePos.setPos(mutablePos2).move(direction)).isTranslucent();
        boolean isTranslucent2 = worldIn.getBlockState(mutablePos.setPos(mutablePos3).move(direction)).isTranslucent();
        boolean isTranslucent3 = worldIn.getBlockState(mutablePos.setPos(mutablePos4).move(direction)).isTranslucent();
        float occlusion;
        int lightVal;
     
        if (!isTranslucent2 && !isTranslucent)
        {
            occlusion = occlusionValue;
            lightVal = light;
        } else
        {
            BlockPos pos = mutablePos.setPos(mutablePos1).move(neighborInfo.corners[2]);
            occlusion = worldIn.getBlockState(pos).getAmbientOcclusionLightValue();
            lightVal = state.getPackedLightmapCoords(worldIn, pos);
        }
     
        float occlusion1;
        int lightVal1;
     
        if (!isTranslucent3 && !isTranslucent)
        {
            occlusion1 = occlusionValue;
            lightVal1 = light;
        } else
        {
            BlockPos pos2 = mutablePos.setPos(mutablePos1).move(neighborInfo.corners[3]);
            occlusion1 = worldIn.getBlockState(pos2).getAmbientOcclusionLightValue();
            lightVal1 = state.getPackedLightmapCoords(worldIn, pos2);
        }
     
        float occlusion2;
        int lightVal2;
     
        if (!isTranslucent2 && !isTranslucent1)
        {
            occlusion2 = occlusionValue1;
            lightVal2 = light1;
        } else
        {
            BlockPos pos3 = mutablePos.setPos(mutablePos2).move(neighborInfo.corners[2]);
            occlusion2 = worldIn.getBlockState(pos3).getAmbientOcclusionLightValue();
            lightVal2 = state.getPackedLightmapCoords(worldIn, pos3);
        }
     
        float occlusion3;
        int lightVal3;
     
        if (!isTranslucent3 && !isTranslucent1)
        {
            occlusion3 = occlusionValue1;
            lightVal3 = light1;
        } else
        {
            BlockPos pos4 = mutablePos.setPos(mutablePos2).move(neighborInfo.corners[3]);
            occlusion3 = worldIn.getBlockState(pos4).getAmbientOcclusionLightValue();
            lightVal3 = state.getPackedLightmapCoords(worldIn, pos4);
        }
     
        int cubeLight = state.getPackedLightmapCoords(worldIn, centerPos);
     
        if (shapeState.get(0) || !worldIn.getBlockState(centerPos.offset(direction)).isOpaqueCube())
        {
            cubeLight = state.getPackedLightmapCoords(worldIn, centerPos.offset(direction));
        }
     
        float shapeOcclusion = shapeState.get(0) ? worldIn.getBlockState(posIn).getAmbientOcclusionLightValue() : worldIn.getBlockState(centerPos).getAmbientOcclusionLightValue();
        BlockModelRenderer.VertexTranslations vertexTranslations = BlockModelRenderer.VertexTranslations.getVertexTranslations(direction);
        mutablePos.release();
        mutablePos1.release();
        mutablePos2.release();
        mutablePos3.release();
        mutablePos4.release();
     
        if (shapeState.get(1) && neighborInfo.doNonCubicWeight)
        {
            float colorMultip = (occlusionValue3 + occlusionValue + occlusion1 + shapeOcclusion) * 0.25F;
            float colorMultip1 = (occlusionValue2 + occlusionValue + occlusion + shapeOcclusion) * 0.25F;
            float colorMultip2 = (occlusionValue2 + occlusionValue1 + occlusion2 + shapeOcclusion) * 0.25F;
            float colorMultip3 = (occlusionValue3 + occlusionValue1 + occlusion3 + shapeOcclusion) * 0.25F;
            //У блока 16 точек, и походу это что-то типа них
            float shape = faceShape[neighborInfo.vert0Weights[0].shape] * faceShape[neighborInfo.vert0Weights[1].shape];
            float shape1 = faceShape[neighborInfo.vert0Weights[2].shape] * faceShape[neighborInfo.vert0Weights[3].shape];
            float shape2 = faceShape[neighborInfo.vert0Weights[4].shape] * faceShape[neighborInfo.vert0Weights[5].shape];
            float shape3 = faceShape[neighborInfo.vert0Weights[6].shape] * faceShape[neighborInfo.vert0Weights[7].shape];
            float shape4 = faceShape[neighborInfo.vert1Weights[0].shape] * faceShape[neighborInfo.vert1Weights[1].shape];
            float shape5 = faceShape[neighborInfo.vert1Weights[2].shape] * faceShape[neighborInfo.vert1Weights[3].shape];
            float shape6 = faceShape[neighborInfo.vert1Weights[4].shape] * faceShape[neighborInfo.vert1Weights[5].shape];
            float shape7 = faceShape[neighborInfo.vert1Weights[6].shape] * faceShape[neighborInfo.vert1Weights[7].shape];
            float shape8 = faceShape[neighborInfo.vert2Weights[0].shape] * faceShape[neighborInfo.vert2Weights[1].shape];
            float shape9 = faceShape[neighborInfo.vert2Weights[2].shape] * faceShape[neighborInfo.vert2Weights[3].shape];
            float shape10 = faceShape[neighborInfo.vert2Weights[4].shape] * faceShape[neighborInfo.vert2Weights[5].shape];
            float shape11 = faceShape[neighborInfo.vert2Weights[6].shape] * faceShape[neighborInfo.vert2Weights[7].shape];
            float shape12 = faceShape[neighborInfo.vert3Weights[0].shape] * faceShape[neighborInfo.vert3Weights[1].shape];
            float shape13 = faceShape[neighborInfo.vert3Weights[2].shape] * faceShape[neighborInfo.vert3Weights[3].shape];
            float shape14 = faceShape[neighborInfo.vert3Weights[4].shape] * faceShape[neighborInfo.vert3Weights[5].shape];
            float shape15 = faceShape[neighborInfo.vert3Weights[6].shape] * faceShape[neighborInfo.vert3Weights[7].shape];
            //Цвет
            this.vertexColorMultiplier[vertexTranslations.vert0] = colorMultip * shape + colorMultip1 * shape1 + colorMultip2 * shape2 + colorMultip3 * shape3;
            this.vertexColorMultiplier[vertexTranslations.vert1] = colorMultip * shape4 + colorMultip1 * shape5 + colorMultip2 * shape6 + colorMultip3 * shape7;
            this.vertexColorMultiplier[vertexTranslations.vert2] = colorMultip * shape8 + colorMultip1 * shape9 + colorMultip2 * shape10 + colorMultip3 * shape11;
            this.vertexColorMultiplier[vertexTranslations.vert3] = colorMultip * shape12 + colorMultip1 * shape13 + colorMultip2 * shape14 + colorMultip3 * shape15;
            //Яркость
            int aoBrightness = this.getAoBrightness(light3, light, lightVal1, cubeLight);
            int aoBrightness1 = this.getAoBrightness(light2, light, lightVal, cubeLight);
            int aoBrightness2 = this.getAoBrightness(light2, light1, lightVal2, cubeLight);
            int aoBrightness3 = this.getAoBrightness(light3, light1, lightVal3, cubeLight);
            //Точка яркости? Точки яркости? Как обычные текстуры только с натягиванием света на область из 4 точек?
            this.vertexBrightness[vertexTranslations.vert0] = this.getVertexBrightness(aoBrightness, aoBrightness1, aoBrightness2, aoBrightness3, shape, shape1, shape2, shape3);
            this.vertexBrightness[vertexTranslations.vert1] = this.getVertexBrightness(aoBrightness, aoBrightness1, aoBrightness2, aoBrightness3, shape4, shape5, shape6, shape7);
            this.vertexBrightness[vertexTranslations.vert2] = this.getVertexBrightness(aoBrightness, aoBrightness1, aoBrightness2, aoBrightness3, shape8, shape9, shape10, shape11);
            this.vertexBrightness[vertexTranslations.vert3] = this.getVertexBrightness(aoBrightness, aoBrightness1, aoBrightness2, aoBrightness3, shape12, shape13, shape14, shape15);
        } else
        {
            float colorMultip = (occlusionValue3 + occlusionValue + occlusion1 + shapeOcclusion) * 0.25F;
            float colorMultip1 = (occlusionValue2 + occlusionValue + occlusion + shapeOcclusion) * 0.25F;
            float colorMultip2 = (occlusionValue2 + occlusionValue1 + occlusion2 + shapeOcclusion) * 0.25F;
            float colorMultip3 = (occlusionValue3 + occlusionValue1 + occlusion3 + shapeOcclusion) * 0.25F;
            //Точка яркости? Точки яркости? Как обычные текстуры только с натягиванием света на область из 4 точек?
            this.vertexBrightness[vertexTranslations.vert0] = this.getAoBrightness(light3, light, lightVal1, cubeLight);
            this.vertexBrightness[vertexTranslations.vert1] = this.getAoBrightness(light2, light, lightVal, cubeLight);
            this.vertexBrightness[vertexTranslations.vert2] = this.getAoBrightness(light2, light1, lightVal2, cubeLight);
            this.vertexBrightness[vertexTranslations.vert3] = this.getAoBrightness(light3, light1, lightVal3, cubeLight);
            //Цвет
            this.vertexColorMultiplier[vertexTranslations.vert0] = colorMultip;
            this.vertexColorMultiplier[vertexTranslations.vert1] = colorMultip1;
            this.vertexColorMultiplier[vertexTranslations.vert2] = colorMultip2;
            this.vertexColorMultiplier[vertexTranslations.vert3] = colorMultip3;
        }
    }
 
    /**
     * Get ambient occlusion brightness
     */
    private int getAoBrightness(int light, int light1, int lightval, int cubeLight)
    {
        if (light == 0)
        {
            light = cubeLight;
        }
     
        if (light1 == 0)
        {
            light1 = cubeLight;
        }
     
        if (lightval == 0)
        {
            lightval = cubeLight;
        }
     
        return light + light1 + lightval + cubeLight >> 2 & 16711935;
    }
 
    private int getVertexBrightness(int aoBrightness, int aoBrightness1, int aoBrightness2, int aoBrightness3, float shape, float shape1, float shape2, float shape3)
    {
        int i = (int) ((float) (aoBrightness >> 16 & 255) * shape +
                (float) (aoBrightness1 >> 16 & 255) * shape1 +
                (float) (aoBrightness2 >> 16 & 255) * shape2 +
                (float) (aoBrightness3 >> 16 & 255) * shape3) & 255;
        int j = (int) ((float) (aoBrightness & 255) * shape +
                (float) (aoBrightness1 & 255) * shape1 +
                (float) (aoBrightness2 & 255) * shape2 +
                (float) (aoBrightness3 & 255) * shape3) & 255;
        return i << 16 | j;
    }
}
 
Последнее редактирование:
Сверху